Gibt es eine Möglichkeit, 'screen' im schreibgeschützten Modus auszuführen?

16

Ich möchte in der Lage sein, den Fortschritt und die Ausgabe meiner vorhandenen screenSitzungen zu überprüfen , aber nur zum Lesen, um zu verhindern, dass aufgrund eines Benutzerfehlers etwas schief geht. Gibt es eine Möglichkeit, dies zu tun?

Naftuli Kay
quelle

Antworten:

8

Leider denke ich, dass die Antwort nein ist. Der Fragesteller ist speziell deshalb auf tmux umgestiegen, weil er diese Funktion hat (Sie übergeben die -rFlagge beim Anhängen). Wenn Sie also die Option haben, Multiplexer zu wechseln, ist dies wahrscheinlich Ihre beste Wahl

Michael Mrozek
quelle
3

Du kannst es versuchen:

aclchg username -w "#"

wenn Sie screenim Mehrbenutzermodus arbeiten (aber ich musste nichts spezielles tun, damit es funktioniert, wenn ich es als einzelner verbundener Benutzer teste). Wenn Sie in den Mehrbenutzermodus wechseln müssen, verwenden Sie multiuser on.

Sie können *für den Benutzernamen verwenden, um alle Benutzer zu beeinflussen.

Verwenden +wanstelle von -waktiviert den Schreibmodus.

Von man screen:

aclchg usernames permbits liste
chacl usernames permbits liste

Ändern Sie die Berechtigungen für eine durch Kommas getrennte Liste von Benutzern. Berechtigungsbits werden als 'r', 'w' und 'x' dargestellt. Das Präfix '+' gewährt die Berechtigung, '-' entfernt sie. Der dritte Parameter ist eine durch Kommas getrennte Liste von Befehlen und / oder Fenstern (angegeben entweder durch Nummer oder Titel). Die Sonderliste '#' bezieht sich auf alle Fenster, '?' zu allen Befehlen. Besteht der Benutzername aus einem einzelnen '*', sind alle bekannten Benutzer betroffen. Ein Befehl kann ausgeführt werden, wenn der Benutzer das 'x'-Bit dafür hat. Der Benutzer kann Eingaben in ein Fenster eingeben, wenn sein "w" -Bit gesetzt ist und kein anderer Benutzer eine Schreibsperre für dieses Fenster erhält. Andere Bits werden derzeit ignoriert. So entfernen Sie die Schreibsperre von einem anderen Benutzer in Fenster 2: 'aclchg Benutzername -w + w 2'. So erlauben Sie den schreibgeschützten Zugriff auf die Sitzung: 'aclchg Benutzername -w "#"'. Sobald bekannt ist, dass der Name eines Benutzers angezeigt wird, kann er eine Verbindung zur Sitzung herstellen und verfügt (standardmäßig) über vollständige Berechtigungen für alle Befehle und Fenster. Die Ausführungsberechtigung für die Befehle acl, at und andere sollte ebenfalls entfernt werden, da der Benutzer sonst möglicherweise die Schreibberechtigung wiedererlangen kann. Die Rechte des speziellen Benutzernamens nobody können nicht geändert werden (siehe den Befehl "su"). 'Chacl' ist ein Synonym für 'aclchg'. Nur Mehrbenutzermodus. und andere sollten ebenfalls entfernt werden, oder der Benutzer kann möglicherweise die Schreibberechtigung wiedererlangen. Die Rechte des speziellen Benutzernamens nobody können nicht geändert werden (siehe den Befehl "su"). 'Chacl' ist ein Synonym für 'aclchg'. Nur Mehrbenutzermodus. und andere sollten ebenfalls entfernt werden, oder der Benutzer kann möglicherweise die Schreibberechtigung wiedererlangen. Die Rechte des speziellen Benutzernamens nobody können nicht geändert werden (siehe den Befehl "su"). 'Chacl' ist ein Synonym für 'aclchg'. Nur Mehrbenutzermodus.

Bis auf weiteres angehalten.
quelle
Das funktioniert zwar, aber es wird nur screenlesbar gemacht, wenn die Bildschirmsitzung angehängt wird, die anders aussieht als die, nach der das OP gefragt hat.
Stéphane Chazelas
1
@StephaneChazelas: Ich sehe keinen Hinweis in der Frage, dass das OP über die Beschreibbarkeit in anderen Fällen einer Sitzung mit mehreren Anhängen besorgt ist. Außerdem kann der aclcngBefehl bestimmte Benutzer, bestimmte Befehle und / oder bestimmte Fenster angeben, so dass die Granularität ziemlich fein ist. Das ist also nicht "überall".
Bis auf weiteres angehalten.
3

Ich habe eine ziemlich einfache Umgehungsmöglichkeit gefunden, mit der man die Ausgabe sicher überwachen kann.

Führen Sie unmittelbar nach dem Aufrufen der Bildschirmsitzung die folgenden Befehle aus:

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

Trenne die Sitzung mit Ctrl-A dund folge der Skriptausgabe, zB:

tail -f /tmp/10751.test
Etikett
quelle
1

Meine aktuelle Lösung hierfür ist, die Terminalansicht auf ReadOnly zu setzen .

Vielleicht ist es zu offensichtlich. Die Frage selbst erforderte jedoch keine Lösung screen.

Sebkraemer
quelle
1
sieht für mich gut aus, mit einem Terminal-Emulator, der den Nur-Lese-Modus unterstützt. leider tun viele terminals nicht (gnome / kde terminal nicht iirc), aber einige tun (wie xfce4-terminal)
hanshenrik
0

Ich habe ein PHP-Skript geschrieben, das aufgerufen wird, readscreenum ... Bildschirmsitzungen im schreibgeschützten Modus beizufügen. Speichern Sie es unter /usr/bin/readscreenund führen chmod 0555 /usr/bin/readscreenSie es aus. Stellen Sie sicher, dass php-cli mit der Erweiterung php-pcntl installiert ist. Anschließend können Sie einen readscreenbeliebigen Befehl eingeben, um eine Verbindung mit dem normalen Bildschirm herzustellen. Beispiel:

readscreen -S foo -x

und Sie werden schreibgeschützt mit der foo-Sitzung verbunden . Beachten Sie, dass es nicht ausführlich getestet wurde, aber gut zu funktionieren scheint. readscreen Quellcode:

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