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.