Existe uma maneira de executar a 'tela' no modo somente leitura?

16

Eu gostaria de poder verificar o progresso e a saída das minhas screensessões existentes , mas de maneira somente leitura, para impedir que algo dê errado devido a erro do usuário. Existe uma maneira de fazer isso?

Naftuli Kay
fonte

Respostas:

8

Infelizmente, acho que a resposta é não. O autor desta pergunta mudou para o tmux especificamente porque possui esse recurso (você passa a -rbandeira ao anexar); portanto, se você tiver a opção de alternar multiplexadores, é provavelmente a melhor escolha

Michael Mrozek
fonte
3

Podes tentar:

aclchg username -w "#"

se você executar screenno modo multiusuário (mas não precisei fazer nada de especial para fazê-lo funcionar ao testá-lo como um único usuário conectado). Se você precisar entrar no modo multiusuário, use multiuser on.

Você pode usar *o nome de usuário para afetar todos os usuários.

Usar em +wvez de -wativa o modo de gravação.

De man screen:

aclchg lista de
permbits de nomes de usuário chacl lista de permbits de nomes de usuário

Altere as permissões para uma lista de usuários separados por vírgula. Os bits de permissão são representados como 'r', 'w' e 'x'. O prefixo '+' concede a permissão, '-' a remove. O terceiro parâmetro é uma lista separada por vírgula de comandos e / ou janelas (especificada por número ou título). A lista especial '#' refere-se a todas as janelas, '?' para todos os comandos. se os nomes de usuário consistirem em um único '*', todos os usuários conhecidos serão afetados. Um comando pode ser executado quando o usuário possui o bit 'x'. O usuário pode digitar a entrada para uma janela quando tiver o bit 'w' definido e nenhum outro usuário obtiver um bloqueio de gravação para esta janela. Outros bits são atualmente ignorados. Para retirar o writelock de outro usuário na janela 2: 'aclchg username -w + w 2'. Para permitir acesso somente leitura à sessão: 'aclchg username -w "#"'. Assim que o nome do usuário é conhecido na tela, ele pode se conectar à sessão e (por padrão) tem permissões totais para todos os comandos e janelas. A permissão de execução para os comandos acl, `at 'e outros também deve ser removida ou o usuário poderá recuperar a permissão de gravação. Direitos do nome de usuário especial ninguém pode ser alterado (consulte o comando "su"). 'Chacl' é sinônimo de 'aclchg'. Somente modo multiusuário. e outros também devem ser removidos ou o usuário poderá recuperar a permissão de gravação. Direitos do nome de usuário especial ninguém pode ser alterado (consulte o comando "su"). 'Chacl' é sinônimo de 'aclchg'. Somente modo multiusuário. e outros também devem ser removidos ou o usuário poderá recuperar a permissão de gravação. Direitos do nome de usuário especial ninguém pode ser alterado (consulte o comando "su"). 'Chacl' é sinônimo de 'aclchg'. Somente modo multiusuário.

Pausado até novo aviso.
fonte
Enquanto isso funciona, é feito screensomente leitura em todos os lugares em que a sessão de tela é anexada, o que parece ser diferente do que o OP pediu.
Stéphane Chazelas
1
@ StephaneChazelas: Não vejo nenhuma indicação na pergunta de que o OP esteja preocupado com a gravabilidade em outros casos de uma sessão com múltiplos anexos. Além disso, o aclcngcomando pode especificar usuários específicos, comandos específicos e / ou janelas específicas, de modo que é uma granularidade bastante fina. Então, isso não está "em todo lugar".
Pausado até novo aviso.
3

Eu encontrei uma solução alternativa bastante simples que permite monitorar a saída com segurança.

Execute os seguintes comandos imediatamente após entrar na sessão da tela:

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

Desanexe a sessão Ctrl-A de siga a saída do script, por exemplo:

tail -f /tmp/10751.test
Tag
fonte
1

Minha solução atual para isso é definir o Terminal View como ReadOnly .

Talvez seja muito óbvio. No entanto, a pergunta não exigia uma solução por screensi só.

sebkraemer
fonte
1
parece bom para mim, com um emulador de terminal que suporta o modo somente leitura. Infelizmente, muitos terminais não (gnome terminal / kde não IIRC), mas alguns fazem (como xfce4-terminal)
hanshenrik
0

eu escrevi um script php chamado readscreenpara ... anexar a sessões de tela no modo somente leitura. salve-o /usr/bin/readscreene execute-o chmod 0555 /usr/bin/readscreene certifique-se de ter o php-cli instalado com a extensão php-pcntl, e você pode escrever readscreenseguido de qualquer comando que usaria para conectar-se à tela normal, por exemplo:

readscreen -S foo -x

e você estará conectado à sessão foo somente leitura . observe que não foi extensivamente testado, mas parece funcionar bem. código fonte da tela de leitura:

#!/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
fonte