ssh로 신호 전달


22

ssh를 통해 신호를 보낼 수 있기를 원합니다 (SIGINT가 가장 중요합니다).

이 명령은

ssh server "sleep 1000;echo f" > foo

서버에서 절전 모드를 시작하고 1000 초 후에 로컬 시스템의 foo 파일에 'f \ n'을 넣습니다. CTRL-C를 누르면 (즉, SIGINT를 ssh로 전송) ssh를 종료하지만 원격 서버에서 절전 모드를 종료하지는 않습니다. 원격 서버에서 절전 모드를 종료하고 싶습니다.

그래서 나는 시도했다 :

ssh server -t "sleep 1000;echo f" > foo

그러나 stdin이 터미널이 아닌 경우이 오류가 발생합니다.

Pseudo-terminal will not be allocated because stdin is not a terminal.

SIGINT는 여전히 전달되지 않습니다.

그래서 나는 시도했다 :

ssh server -t -t "sleep 1000;echo f" > output

그러나 foo의 출력은 'f \ n'이 아니라 대신 내 상황에서 비참한 'f \ r \ n'입니다 (출력이 이진 데이터이므로).

위에서는 "sleep 1000; echo f"를 사용하지만 실제로는 사용자가 제공 한 것이므로 아무 것도 포함 할 수 있습니다. 그러나 "sleep 1000; echo f"에서 작동하도록 설정하면 모든 현실적인 상황에서 작동하도록 할 수 있습니다.

나는 실제로 다른 쪽 끝에 의사 터미널을 얻는 것에 신경 쓰지 않지만 SIGINT를 전달하기 위해 ssh를 얻는 다른 방법을 찾지 못했습니다.

다른 방법이 있습니까?

편집하다:

사용자는 stdin에서 이진 데이터를 읽는 명령을 제공 할 수 있습니다.

seq 1000 | gzip | ssh server "zcat|bzip2; sleep 1000" | bzcat > foo

사용자는 다음과 같이 CPU를 많이 사용하는 명령을 제공 할 수 있습니다.

ssh server "timeout 1000 burnP6"

편집 2 :

나에게 맞는 버전은 다음과 같습니다.

your_preprocessing |
  uuencode a | ssh -tt -oLogLevel=quiet server "stty isig -echoctl -echo ; uudecode -o - |
your_command |
  uuencode a" | uudecode -o - |
your_postprocessing

올바른 방향으로 나를 가리켜 준 digital_infinity 덕분에.


1
나는의 실제 사용을 생각 ssh하면 간단한 재 배열하여 원하는 동작을 얻을 수 있기 때문에, 더 당신이 예로 표시 것보다 복잡합니다 sleep 1000 && ssh server "echo f" > foo(그것은이 될 수 &&,하지 ;, 그래서 살인 sleep을 방지에게 ssh. 실행 명령)하는 경우 I 맞습니다. 실제 사용량을 더 잘 대표 할 수 있도록 더 나은 답변을 드릴 수 있도록 예제를 작성하십시오.
워렌 영

올바른 : sleep 및 echo는 실제로 사용자 제공 스크립트이며 문자 그대로 sleep 및 echo가 아닙니다. 그래서 우리는 그들이 무엇을하는지 모르고 최악의 상황을 가정해야합니다.
Ole Tange

Sooo ... 더 나은 예제 명령을 내놓을 것입니다. 간단한 재배치로 문제가 해결되지 않는 이유는 무엇입니까? 좋은 질문을했는데 답변을보고 싶지만 "그렇게하지 않으면"대답이 합리적이라면 답변을받을 가능성이 줄어 듭니다.
워렌 영

그건 그렇고 ...하지 마라;)
Tim

질문에서 ":"위에서 "잠자기 1000; 에코 f"를 사용하지만 실제로는 사용자가 제공 한 것이므로 무엇이든 포함 할 수 있습니다 "" "
Ole Tange

답변:


10

짧은 답변:

ssh -t fs "stty isig intr ^N -echoctl ; trap '/bin/true' SIGINT; sleep 1000; echo f" > foo

CTRL + N으로 프로그램을 중지하십시오.

긴 설명 :

  1. 서버 또는 로컬 인터럽트 문자 를 변경 하려면 stty옵션 intr을 사용해야합니다 가 서로 충돌하지 않도록 . 위의 명령에서 서버 인터럽트 문자를 CTRL + N으로 변경했습니다. 로컬 인터럽트 문자를 변경하고 변경없이 서버의 문자를 그대로 둘 수 있습니다.
  2. 인터럽트 문자가 출력 (및 기타 제어 문자)에 포함되지 않게하려면을 사용하십시오 stty -echoctl.
  3. sshd에 의해 호출 된 서버 bash에서 제어 문자가 켜져 있는지 확인해야합니다. 그렇지 않으면 로그 아웃 한 후에도 여전히 프로세스가 중단 될 수 있습니다.stty isig
  4. 실제로 빈 문장으로 SIGINT신호를 잡습니다 trap '/bin/true' SIGINT. 함정이 없으면 SIGINT 신호가 끝난 후에는 stdout이 없습니다.

바이너리 입력을 잘 다루지 않는 것 같습니다 : seq 1000 | gzip | ssh -t -t 서버 "stty isig intr ^ N -echoctl; 트랩 '/ bin / true'SIGINT; 수면 1; zcat | bzip2"| bzcat> foo;
Ole Tange

콘솔 이외의 다른 것에 대해 ssh에 대한 표준 입력을 설정하면 콘솔로 인터럽트 할 수 없습니다. 이 경우 stdin 스트림에 의해 인터럽트되어야합니다.
digital_infinity

나는 이것이 seq 1000 | gzip | ssh -tt dell-test "zcat|bzip2" | bzcat > foo작동하지 않는 것을 발견했다 . 이 명령이 작동하도록하려면 제거해야합니다 -tt. 의사 터미널 할당은 아마 표준 입력에서 일부 입력합니다 그래서
digital_infinity

나는 uuencode를 시도했다. 이 버전에서는 작동하지 않습니다. cat foo.gz | perl -ne '인쇄 팩 ( "u", $ _)'| ssh -t -t 서버 'perl -ne "print unpack (\"u \ ", \ $ _)"| zcat | gzip | perl -ne "인쇄 팩 (\"u \ ", \ $ _)" '| perl -ne 'print unpack ( "u", $ _)'> foo2.gz
Ole Tange

1
나는 이것을 가지고있다 : (sleep 1; seq 1000 ) | gzip | uuencode bin | ssh -tt dell-test "stty isig intr ^N -echoctl -echo ; trap '/bin/true' SIGINT; sleep 1; uudecode -o /dev/stdout | zcat |bzip2 | uuencode bin2 " | uudecode -o /dev/stdout | bzcat >foo. 인터럽트 문자가 작동하지 않더라도 stdin이 사용 중인 동안 인터럽트 문자에 대한 전송 방법이 필요합니다 .
digital_infinity

3

나는 모든 해결책을 시도했으며 이것이 최고였습니다.

ssh host "sleep 99 < <(cat; kill -INT 0)" <&1

/programming/3235180/starting-a-process-over-ssh-using-bash-and-then-killing-it-on-sigint/25882610#25882610


sleep연결이 끊어진 경우 프로세스를 중지하지 않습니다 .
blueyed

연결이 끊어지면 stdin이 차단되어 고양이를 차단 해제하여 프로세스 그룹을 종료시킵니다. INTerrupt 신호가 작업에 충분한 지 여부는 다른 질문입니다.
에릭 우드 러프

그것으로 충분 sleep해야합니까? 다음에 일부 date >> /tmp/killed를 추가 cat했지만 트리거되지 않았습니다. 타임 아웃이 있습니까? Zsh를 정상적으로 사용하고 있지만 원격 로그인 쉘로 bash를 사용하여 테스트했습니다.
blueyed

나는 당신이 연결 시간 초과의 자비에 있다고 생각합니다.
Eric Woodruff

이것을 제어하는 ​​설정이 있습니까? 클라이언트 측에서는 -o ServerAliveInterval=3 -o ServerAliveCountMax=2신속하게 감지 할 수 있지만 서버 측에는 무언가가 있습니까?
blueyed

2

서버에서 실행중인 프로세스의 PID를 찾고 다른 ssh명령 (예 :)을 사용하여 신호를 보낼 수 있다고 생각합니다 ssh server "kill -2 PID".

이 방법을 사용하여 재구성 신호를 다른 컴퓨터에서 실행중인 응용 프로그램으로 보냅니다 (응용 프로그램은 SIGUSR1을 잡고 구성 파일을 읽습니다). 필자의 경우 고유 한 프로세스 이름이 있고 ps를 통해 요청을 보내 PID를 찾을 수 있기 때문에 PID를 찾는 것이 쉽습니다 ssh.


원격에서 실행중인 프로그램의 PID를 찾는 방탄 방법이 보이지 않습니다. 사용자가 제공 한 것을 기억하십시오. ssh server 'exec $ (echo fyrrc 1000 | / usr / games / rot13)'
Ole Tange

1

솔루션은 http://www.gnu.org/software/parallel/parallel_design.html#Remote-Ctrl-C-and-standard-error-stderr 로 발전했습니다 .

$SIG{CHLD} = sub { $done = 1; };
$pid = fork;
unless($pid) {
    # Make own process group to be able to kill HUP it later
    setpgrp;
    exec $ENV{SHELL}, "-c", ($bashfunc."@ARGV");
    die "exec: $!\n";
}
do {
    # Parent is not init (ppid=1), so sshd is alive
    # Exponential sleep up to 1 sec
    $s = $s < 1 ? 0.001 + $s * 1.03 : $s;
    select(undef, undef, undef, $s);
} until ($done || getppid == 1);
# Kill HUP the process group if job not done
kill(SIGHUP, -${pid}) unless $done;
wait;
exit ($?&127 ? 128+($?&127) : 1+$?>>8)

0

----- command.sh

#! /bin/sh
trap 'trap - EXIT; kill 0; exit' EXIT
(sleep 1000;echo f) &
read ans

로컬 터미널에서 -----

sleep 864000 | ssh -T server command.sh > foo

안녕! 관련성이 있다고 생각되는 한, 그것이 어떻게 작동하는지 설명함으로써 답변을 훨씬 더 유용하게 만들 수 있다고 생각합니다. 새로운 정보를 삽입하기 위해 망설이지 말고 편집하십시오.
dhag
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.