¿Hay alguna manera de ejecutar 'pantalla' en modo de solo lectura?

16

Me gustaría poder verificar el progreso y la salida de mis screensesiones existentes , pero de manera de solo lectura, para evitar que algo salga mal debido a un error del usuario. ¿Hay alguna forma de hacer esto?

Naftuli Kay
fuente

Respuestas:

8

Desafortunadamente, creo que la respuesta es no. El autor de esta pregunta cambió a tmux específicamente porque tiene esa característica (pasa la -rbandera al adjuntar), por lo que si tiene la opción de cambiar multiplexores, probablemente sea su mejor opción

Michael Mrozek
fuente
3

Puedes probar:

aclchg username -w "#"

si ejecuta screenen modo multiusuario (pero no tuve que hacer nada especial para que funcionara al probarlo como un solo usuario adjunto). Si necesita ingresar al modo multiusuario, use multiuser on.

Puede usar *el nombre de usuario para afectar a todos los usuarios.

Usar en +wlugar de -whabilitar el modo de escritura.

De man screen:

aclchg lista de
permbits de nombres de usuario chacl lista de permbits de nombres de usuario

Cambie los permisos para una lista de usuarios separados por comas. Los bits de permiso se representan como 'r', 'w' y 'x'. El prefijo '+' otorga el permiso, '-' lo elimina. El tercer parámetro es una lista separada por comas de comandos y / o ventanas (especificada por número o título). La lista especial '#' se refiere a todas las ventanas, '?' a todos los comandos. si los nombres de usuario consisten en un solo '*', todos los usuarios conocidos se ven afectados. Se puede ejecutar un comando cuando el usuario tiene el bit 'x' para ello. El usuario puede escribir la entrada en una ventana cuando tiene su bit 'w' establecido y ningún otro usuario obtiene un bloqueo de escritura para esta ventana. Otros bits se ignoran actualmente. Para retirar el bloqueo de escritura de otro usuario en la ventana 2: 'aclchg username -w + w 2'. Para permitir el acceso de solo lectura a la sesión: 'aclchg username -w "#"'. Tan pronto como se sepa el nombre de un usuario en la pantalla, puede adjuntarlo a la sesión y (por defecto) tiene permisos completos para todos los comandos y ventanas. El permiso de ejecución para los comandos acl, `at 'y otros también deben eliminarse o el usuario podrá recuperar el permiso de escritura. Los derechos del nombre de usuario especial no se pueden cambiar (ver el comando "su"). 'Chacl' es sinónimo de 'aclchg'. Modo multiusuario solamente. y otros también deben ser eliminados o el usuario puede recuperar el permiso de escritura. Los derechos del nombre de usuario especial no se pueden cambiar (ver el comando "su"). 'Chacl' es sinónimo de 'aclchg'. Modo multiusuario solamente. y otros también deben ser eliminados o el usuario puede recuperar el permiso de escritura. Los derechos del nombre de usuario especial no se pueden cambiar (ver el comando "su"). 'Chacl' es sinónimo de 'aclchg'. Modo multiusuario solamente.

Pausado hasta nuevo aviso.
fuente
Si bien eso funciona, solo se screenlee en todas partes donde se adjunta la sesión de pantalla, lo que parece ser diferente de lo que solicitó el OP.
Stéphane Chazelas
1
@StephaneChazelas: No veo ninguna indicación en la pregunta de que el OP esté preocupado por la capacidad de escritura en otros casos de una sesión con múltiples enlaces. Además, el aclcngcomando puede especificar usuarios particulares, comandos particulares y / o ventanas particulares, por lo que es una granularidad bastante fina. Entonces eso no está "en todas partes".
Pausado hasta nuevo aviso.
3

He encontrado una solución bastante simple que permite monitorear la salida de forma segura.

Ejecute los siguientes comandos inmediatamente después de ingresar a la sesión de pantalla:

echo /tmp/$STY
touch /tmp/$STY
chmod 0600 /tmp/$STY
script -a -f /tmp/$STY

Separe la sesión con Ctrl-A dy siga la salida del script, por ejemplo:

tail -f /tmp/10751.test
Etiqueta
fuente
1

Mi solución actual para esto es establecer la Vista de terminal en Solo lectura .

Quizás es demasiado obvio. Sin embargo, la pregunta no requería una solución por screensí misma.

sebkraemer
fuente
1
me parece bien, con un emulador de terminal que admite el modo de solo lectura. Por desgracia, muchos terminales no (gnome / terminal de KDE hace no IIRC), pero algunos lo hacen (como xfce4-terminal)
hanshenrik
0

Escribí un script php llamado readscreena ... adjuntar a sesiones de pantalla en modo de solo lectura. guárdelo /usr/bin/readscreeny ejecútelo chmod 0555 /usr/bin/readscreen, y asegúrese de tener php-cli instalado con la extensión php-pcntl, y puede escribir readscreenseguido del comando que usaría para conectarse con la pantalla normal, por ejemplo:

readscreen -S foo -x

y estarás conectado a la sesión foo de solo lectura . Tenga en cuenta que no se ha probado exhaustivamente, pero parece funcionar bien. código fuente de la pantalla de lectura:

#!/usr/bin/env php
<?php
declare(ticks = 1);
init_signals ();
$args = $argv;
unset ( $args [0] );
$args = implode ( " ", array_map ( 'escapeshellarg', $args ) );
// var_dump ( $argc, $argv, $args );

$cmd = "screen {$args}";
echo "executing cmd: $cmd\n";
$descriptorspec = array (
        0 => array (
                "pipe",
                "rb" 
        ) // stdin
);
$cwd = NULL;
$env = NULL;
global $screen;
$screen = proc_open ( "script --quiet --return --command " . escapeshellarg ( $cmd )." /dev/null", $descriptorspec, $pipes, $cwd, $env );
global $screen_stdin;
$screen_stdin = $pipes [0];
if (false === $screen) {
    echo ("error: failed creating screen process: ");
    var_dump ( error_get_last () );
    die ( 1 );
}
//fclose(STDIN);
while ( 1 ) {
    //echo ".";
    sleep ( 1 );
    if (! proc_get_status ( $screen ) ['running']) {
        echo "error: screen stopped.\n";
        cleanup ();
        die ( 1 );
    }
}
function cleanup() {
    global $screen;
    global $screen_stdin;
    echo "detaching from screen. (running cleanup() )\n";
    fwrite ( $screen_stdin, "\01" ); // equivalent of ctrl+AD apparently.
    fclose ( $screen_stdin );
    $exited = false;
    // give it a few seconds to exit itself before killing it
    for($i = 0; $i < 3; ++ $i) {
        if (! proc_get_status ( $screen ) ['running']) {
            $exited = true;
            break;
        }
        sleep ( 1 );
    }
    if (! $exited) {
        echo "Warning: screen did not exit gracefully, killing it now..";
        proc_terminate ( $screen, SIGKILL );
        while ( proc_get_status ( $screen ) ['running'] ) {
            echo ".";
            sleep ( 1 );
        }
        echo "killed.";
    }
    proc_close ( $screen );
}
function init_signals() {
    global $signals;
    // all signals that cause termination by default.
    $signals = [ 
            "SIGABRT",
            "SIGALRM",
            "SIGFPE",
            "SIGHUP",
            "SIGILL",
            "SIGINT",
            // "SIGKILL",
            "SIGPIPE",
            "SIGQUIT",
            "SIGSEGV",
            "SIGTERM",
            "SIGUSR1",
            "SIGUSR2",
            "SIGBUS",
            "SIGPOLL",
            "SIGPROF",
            "SIGSYS",
            "SIGTRAP",
            "SIGVTALRM",
            "SIGXCPU",
            "SIGXFSZ" 
    ];
    $signals_new = [ ];
    foreach ( $signals as $key => $signal ) {
        $tmp = constant ( $signal );
        if ($tmp === null) {
            fprintf ( STDERR, "warning: unknown signal \"%s\", may not be able to handle it without passing it to screen...\n", $singal );
            unset ( $signals [$key] );
            continue;
        }
        $signals_new [$signal] = $tmp;
    }
    $signals = $signals_new;
    unset ( $signals_new );
    foreach ( $signals as $num ) {
        pcntl_signal ( $num, "signal_handler" );
    }
}
function signal_handler($signo, $siginfo) {
    global $signals;
    $sname = array_search ( $signo, $signals, false );
    if ($sname === false) {
        $sname = "unknown signal";
    }
    echo "\n\nerror: got signal " . $signo . " (" . $sname . "), exiting screen session & returning.\n";
    var_dump ( $siginfo );
    cleanup ();
    die ();
}
Hanshenrik
fuente