Existe-t-il un moyen d'exécuter «écran» en mode lecture seule?

16

Je voudrais pouvoir vérifier la progression et la sortie de mes screensessions existantes , mais en lecture seule, afin d'éviter que quelque chose ne se passe mal en raison d'une erreur de l'utilisateur. Y a-t-il un moyen de faire cela?

Naftuli Kay
la source

Réponses:

8

Malheureusement, je pense que la réponse est non. Le demandeur de cette question est passé à tmux spécifiquement parce qu'il a cette fonctionnalité (vous passez le -rdrapeau lors de la connexion), donc si vous avez la possibilité de changer de multiplexeur, c'est probablement votre meilleur choix

Michael Mrozek
la source
3

Tu peux essayer:

aclchg username -w "#"

si vous exécutez screenen mode multi-utilisateur (mais je n'ai rien eu à faire de spécial pour le faire fonctionner lors du test en tant qu'utilisateur connecté unique). Si vous devez entrer en mode multi-utilisateur, utilisez multiuser on.

Vous pouvez utiliser *le nom d'utilisateur pour affecter tous les utilisateurs.

Utiliser +wau lieu d' -wactiver le mode d'écriture.

De man screen:

aclchg liste des
noms d'utilisateurs permbits chacl liste des noms d'utilisateurs permbits

Modifiez les autorisations pour une liste d'utilisateurs séparés par des virgules. Les bits d'autorisation sont représentés par «r», «w» et «x». Le préfixe «+» accorde l'autorisation, «-» la supprime. Le troisième paramètre est une liste de commandes et / ou fenêtres séparées par des virgules (spécifiées soit par un numéro, soit par un titre). La liste spéciale '#' fait référence à toutes les fenêtres, '?' à toutes les commandes. si les noms d'utilisateur se composent d'un seul '*', tous les utilisateurs connus sont affectés. Une commande peut être exécutée lorsque l'utilisateur a le bit 'x' pour cela. L'utilisateur peut saisir une entrée dans une fenêtre lorsqu'il a son bit «w» défini et aucun autre utilisateur n'obtient un verrou en écriture pour cette fenêtre. Les autres bits sont actuellement ignorés. Pour retirer le writelock d'un autre utilisateur dans la fenêtre 2: 'aclchg username -w + w 2'. Pour autoriser l'accès en lecture seule à la session: 'aclchg username -w "#"'. Dès que le nom d'un utilisateur est connu à l'écran, il peut se joindre à la session et (par défaut) dispose de toutes les autorisations pour toutes les commandes et fenêtres. L'autorisation d'exécution pour les commandes acl, «at» et autres doit également être supprimée ou l'utilisateur peut être en mesure de regagner l'autorisation d'écriture. Les droits du nom d'utilisateur spécial ne peuvent pas être modifiés (voir la commande "su"). 'Chacl' est synonyme de 'aclchg'. Mode multi-utilisateur uniquement. et d'autres doivent également être supprimés ou l'utilisateur peut être en mesure de retrouver l'autorisation d'écriture. Les droits du nom d'utilisateur spécial ne peuvent pas être modifiés (voir la commande "su"). 'Chacl' est synonyme de 'aclchg'. Mode multi-utilisateur uniquement. et d'autres doivent également être supprimés ou l'utilisateur peut être en mesure de retrouver l'autorisation d'écriture. Les droits du nom d'utilisateur spécial ne peuvent pas être modifiés (voir la commande "su"). 'Chacl' est synonyme de 'aclchg'. Mode multi-utilisateur uniquement.

En pause jusqu'à nouvel ordre.
la source
Bien que cela fonctionne, cela ne fait que screenlire partout où la session d'écran est attachée, ce qui ressemble à ce que l'OP a demandé.
Stéphane Chazelas
1
@StephaneChazelas: Je ne vois aucune indication dans la question que l'OP est préoccupé par l'écriture dans d'autres cas d'une session à plusieurs attachements. En outre, la aclcngcommande peut spécifier des utilisateurs particuliers, des commandes particulières et / ou des fenêtres particulières, ce qui donne une granularité assez fine. Ce n'est donc pas "partout".
pause jusqu'à nouvel ordre.
3

J'ai trouvé une solution de contournement assez simple qui permet de surveiller la sortie en toute sécurité.

Exécutez les commandes suivantes immédiatement après avoir accédé à la session écran:

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

Détachez la session avec Ctrl-A det suivez la sortie du script, par exemple:

tail -f /tmp/10751.test
Étiquette
la source
1

Ma solution actuelle consiste à définir la vue du terminal sur ReadOnly .

C'est peut-être trop évident. Cependant, la question ne nécessitait pas de solution en screensoi.

sebkraemer
la source
1
me semble bien, avec un émulateur de terminal qui prend en charge le mode lecture seule. malheureusement, de nombreux terminaux ne le font pas (le terminal gnome / kde ne fait pas iirc), mais certains le font (comme xfce4-terminal)
hanshenrik
0

j'ai écrit un script php appelé readscreenpour ... attacher aux sessions d'écran en mode lecture seule. enregistrez-le /usr/bin/readscreenet exécutez chmod 0555 /usr/bin/readscreen, et assurez-vous que php-cli est installé avec l'extension php-pcntl, et vous pouvez écrire readscreensuivi de la commande que vous utiliseriez pour vous connecter à l'écran normal, par exemple:

readscreen -S foo -x

et vous serez connecté à la session foo en lecture seule . notez qu'il n'est pas largement testé, mais semble bien fonctionner. code source de l'écran de lecture:

#!/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
la source