[unix] 읽기 전용 모드에서 ‘스크린’을 실행하는 방법이 있습니까?

기존 screen세션 의 진행 상황과 출력을 확인 하지만 읽기 전용 방식으로 사용자 오류로 인해 무언가 잘못되는 것을 방지하고 싶습니다 . 이것을 할 수있는 방법이 있습니까?



답변

불행히도 대답은 ‘아니오’라고 생각합니다. 의 아스 커 이 문제는 로 전환 TMUX 가 그 기능을 (당신이 통과 있기 때문에 특별히 -r당신이 멀티플렉서를 전환 할 수있는 옵션이있는 경우에 그래서 아마 당신의 최선의 선택이다, 부착 할 때 플래그)


답변

당신은 시도 할 수 있습니다:

aclchg username -w "#"

screen다중 사용자 모드에서 실행하는 경우 (단 하나의 연결된 사용자로 테스트 할 때 특별한 작업을 수행 할 필요가 없습니다). 다중 사용자 모드로 들어가야하는 경우을 사용하십시오 multiuser on.

당신이 사용할 수있는 *모든 사용자에게 영향을하기 위해 사용자 이름.

사용은 +w대신 -w쓰기 모드를 가능하게한다.

보낸 사람 man screen:

aclchg 사용자 이름 permbits 목록
chacl 사용자 이름 permbits 목록

쉼표로 구분 된 사용자 목록에 대한 권한을 변경하십시오. 권한 비트는 ‘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’와 동의어입니다. 다중 사용자 모드 만 해당.


답변

출력을 안전하게 모니터링 할 수있는 상당히 간단한 해결 방법을 찾았습니다.

스크린 세션에 들어간 직후 다음 명령을 실행하십시오.

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

Ctrl-A d다음과 같이 세션을 분리하고 스크립트 출력을 따르십시오.

tail -f /tmp/10751.test


답변

이것에 대한 나의 현재 해결책은 터미널보기를 ReadOnly 로 설정하는 것 입니다.

어쩌면 너무 분명 할 수도 있습니다. 그러나 질문 screen자체 에는 해결책이 필요하지 않았습니다 .


답변

readscreen읽기 전용 모드에서 화면 세션에 연결 하는 PHP 스크립트를 작성했습니다 . 저장 /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 ();
}


답변