Есть ли способ запустить «экран» в режиме только для чтения?

16

Я хотел бы иметь возможность проверять ход и результаты моих существующих screenсеансов, но только для чтения, чтобы не допустить неправильной работы из-за ошибки пользователя. Есть ли способ сделать это?

Нафтули Кей
источник

Ответы:

8

К сожалению, я думаю, что ответ - нет. Ответчик на этот вопрос переключился на tmux именно потому, что он имеет эту функцию (вы устанавливаете -rфлаг при подключении), поэтому, если у вас есть возможность переключать мультиплексоры, это, вероятно, ваш лучший выбор

Михаил Мрозек
источник
3

Можешь попробовать:

aclchg username -w "#"

если вы работаете screenв многопользовательском режиме (но мне не нужно было делать ничего особенного, чтобы заставить его работать при тестировании как однопользовательский пользователь). Если вам нужно войти в многопользовательский режим, используйте multiuser on.

Вы можете использовать *для имени пользователя, чтобы повлиять на всех пользователей.

Использование +wвместо -wвключает режим записи.

От man screen:

список
разрешений userls aclchg список разрешений usernames chacl

Изменить разрешения для списка пользователей через запятую. Биты разрешения представлены как 'r', 'w' и 'x'. Префикс «+» дает разрешение, «-» удаляет его. Третий параметр - это список команд и / или окон, разделенных запятыми (указывается либо номером, либо названием). Специальный список «#» относится ко всем окнам «?» на все команды. если имена пользователей состоят из одного '*', затрагиваются все известные пользователи. Команда может быть выполнена, когда у пользователя есть бит «x». Пользователь может вводить данные в окно, когда у него установлен бит w, и никакой другой пользователь не получает блокировку записи для этого окна. Другие биты в настоящее время игнорируются. Чтобы снять блокировку записи с другого пользователя в окне 2: «aclchg username -w + w 2». Чтобы разрешить доступ только для чтения к сеансу: 'aclchg username -w "#"'. Как только имя пользователя известно на экране, он может присоединиться к сеансу и (по умолчанию) имеет полные разрешения для всех команд и окон. Разрешение на выполнение команд acl, `at 'и других также должно быть удалено, иначе пользователь сможет восстановить разрешение на запись. Права специального имени пользователя никто не может быть изменен (см. Команду «su»). «Chacl» является синонимом «aclchg». Только многопользовательский режим. и другие также должны быть удалены, иначе пользователь сможет восстановить разрешение на запись. Права специального имени пользователя никто не может быть изменен (см. Команду «su»). «Chacl» является синонимом «aclchg». Только многопользовательский режим. и другие также должны быть удалены, иначе пользователь сможет восстановить разрешение на запись. Права специального имени пользователя никто не может быть изменен (см. Команду «su»). «Chacl» является синонимом «aclchg». Только многопользовательский режим.

Приостановлено до дальнейшего уведомления.
источник
Несмотря на то, что это работает, оно делает screenreadonly везде, где присоединяется сеанс экрана, что, похоже, отличается от того, что запрашивал OP.
Стефан Шазелас
1
@StephaneChazelas: Я не вижу никаких признаков в вопросе, что OP обеспокоен возможностью записи в других случаях многократного присоединения сеанса. Кроме того, aclcngкоманда может указывать конкретных пользователей, конкретные команды и / или определенные окна, так что это довольно хорошая детализация. Так что это не "везде".
Приостановлено до дальнейшего уведомления.
3

Я нашел довольно простой обходной путь, который позволяет безопасно контролировать вывод.

Выполните следующие команды сразу после входа в сеанс экрана:

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

Отключите сеанс Ctrl-A dи следуйте выводу скрипта, например:

tail -f /tmp/10751.test
Тег
источник
1

Мое текущее решение для этого состоит в том, чтобы установить Terminal View на ReadOnly .

Может быть, это слишком очевидно. Однако вопрос сам по себе не требовал решения screen.

sebkraemer
источник
1
выглядит хорошо для меня, с эмулятором терминала, который поддерживает режим только для чтения. к сожалению, многие терминалы этого не делают (терминал gnome / kde не поддерживает iirc), но некоторые делают (например, xfce4-терминал)
hanshenrik
0

я написал скрипт php, который называется readscreen... прикреплять к сеансам экрана в режиме только для чтения. сохраните его /usr/bin/readscreenи запустите chmod 0555 /usr/bin/readscreen, убедитесь, что у вас установлен php-cli с расширением php-pcntl, и вы можете написать readscreenлюбую команду, которую вы используете для подключения к обычному экрану, например:

readscreen -S foo -x

и вы будете подключены к сессии foo только для чтения . обратите внимание, что он не был тщательно протестирован, но, кажется, работает нормально. читать исходный код:

#!/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
источник