有没有办法在只读模式下运行“屏幕”?


16

我希望能够以screen只读方式检查现有会话的进度和输出,以防止由于用户错误而出错。有没有办法做到这一点?

Answers:


8

不幸的是,我认为答案是否定的。的提问者这个问题,切换到TMUX特别是因为它有这个功能(你通过-r连接在标志),所以如果你有切换多路复用器选项它可能是您最好的选择


3

你可以试试:

aclchg username -w "#"

如果您screen以多用户模式运行(但在以单个附加用户身份对其进行测试时,我无需做任何特殊的事情即可使其运行)。如果确实需要进入多用户模式,请使用multiuser on

您可以使用*用户名来影响所有用户。

使用+w代替-w启用写入模式。

来自man screen

aclchg用户名权限列表
chacl用户名权限列表

更改以逗号分隔的用户列表的权限。权限位表示为“ r”,“ w”和“ x”。前缀“ +”将授予权限,“-”将其删除。第三个参数是逗号分隔的命令和/或窗口列表(由数字或标题指定)。特殊列表“#”指的是所有窗口“?” 所有命令。如果用户名由单个“ *”组成,则所有已知用户均会受到影响。当用户使用“ x”位时可以执行命令。当用户将其“ w”位置1且没有其他用户获得该窗口的写锁时,可以在该窗口中键入输入。当前忽略其他位。要从窗口2中的另一个用户撤回写锁:“ aclchg用户名-w + w 2”。要允许对会话的只读访问:'aclchg username -w“#”'。一旦知道了用户名,他就可以附加到会话,并且(默认情况下)对所有命令和窗口具有完全权限。还应删除acl命令,“ at”和其他命令的执行权限,否则用户可能会重新获得写权限。特殊用户名的权限nobody不能更改(请参见“ su”命令)。“ Chacl”是“ aclchg”的同义词。仅限多用户模式。其他内容也应删除,否则用户可能会重新获得写权限。特殊用户名的权限nobody不能更改(请参见“ su”命令)。“ Chacl”是“ aclchg”的同义词。仅限多用户模式。其他内容也应删除,否则用户可能会重新获得写权限。特殊用户名的权限nobody不能更改(请参见“ su”命令)。“ Chacl”是“ aclchg”的同义词。仅限多用户模式。


在这种情况下,它可以使screen连接屏幕会话的所有地方都变为只读状态,这看起来与OP要求的有所不同。
斯特凡Chazelas

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

我当前的解决方案是将终端视图设置为ReadOnly

也许太明显了。但是,这个问题本身并不需要解决方案screen


1
通过支持只读模式的终端仿真器,对我来说看起来不错。不幸的是,很多终端都没有(gnome / kde终端没有iirc),但是有些却没有(例如xfce4-terminal)
hanshenrik

0

我写了一个PHP脚本,名为readscreen...以只读模式附加到屏幕会话。保存/usr/bin/readscreen并运行chmod 0555 /usr/bin/readscreen,并确保安装了带有php-pcntl扩展名的php-cli,然后可以编写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 ();
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.