Eu escrevi um script php chamado readscreen
para ... anexar a sessões de tela no modo somente leitura. salve-o em /usr/bin/readscreen
e execute chmod 0555 /usr/bin/readscreen
, e certifique-se de ter o php-cli instalado com a extensão php-pcntl, e você pode escrever readscreen
seguido por qualquer comando que você usasse para conectar-se à tela normal, por exemplo :
readscreen -S foo -x
e você estará conectado à sessão foo de maneira somente leitura . note que ele não é extensivamente testado, mas parece funcionar bem. código fonte de leitura:
#!/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, "" ); // 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 ();
}