Sinyalleri iletmek için ssh alın


22

Ssh ile sinyal gönderebilmek istiyorum (SIGINT en önemlisidir).

Bu komut:

ssh server "sleep 1000;echo f" > foo

sunucuda uykuya başlayacak ve 1000 saniye sonra yerel makinemdeki foo dosyasına 'f \ n' girecek. CTRL-C tuşlarına basarsam (yani SshINT'i ssh'ye gönder), ssh'yi öldürür, ancak uzak sunucudaki uykuyı öldürmez. Uzaktaki sunucuda uykuyı öldürmesini istiyorum.

Bu yüzden denedim:

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

Fakat stdin bir terminal değilse, bu hatayı alıyorum:

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

ve sonra SIGINT hala iletilmemiştir.

Bu yüzden denedim:

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

Ama sonra foo'daki çıktı 'f \ n' değil, benim durumumda feci olan 'f \ r \ n' (çıktım ikili veri olduğundan).

Yukarıdakilerde "sleep 1000; echo f" kullanıyorum, ancak gerçekte kullanıcı tarafından sağlanan gerçekte, her şeyi içerebilir. Bununla birlikte, eğer "uyku 1000; eko f" için çalışabilirsek, büyük olasılıkla tüm gerçekçi durumlar için çalışmasını sağlayabiliriz.

Diğer ucunda takma bir terminal almak umrumda değil, ancak SIGINT'imi iletmek için ssh kullanmanın başka bir yolunu bulamadım.

Başka bir yolu var mı?

Düzenle:

Kullanıcı, örneğin stdin'den ikili verileri okuyan komutlar verebilir:

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

Kullanıcı cpu yoğun komutlar verebilir, örneğin:

ssh server "timeout 1000 burnP6"

Edit2:

Benim için çalışıyor gibi görünen sürüm:

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

Beni doğru yöne işaret eden digital_infinity sayesinde.


1
Bence asıl kullanımınız, sshörnek olarak gösterdiğinizden daha karmaşık olmalıdır, çünkü istediğiniz davranışı basit bir yeniden düzenleme ile elde edebilirsiniz: sleep 1000 && ssh server "echo f" > foo( Öldürme komutunun çalışmasını engellemek için , öyle &&olmamalıdır .) Ben haklıyım, lütfen örneklerinizi gerçek kullanımınız için daha temsili kılın, böylece daha iyi bir cevap verilebilir. ;sleepssh
Warren Young,

Doğru: uyku ve yankı aslında kullanıcı tarafından sağlanan komut dosyalarıdır ve tam anlamıyla uyku ve yankı değildir. Bu yüzden ne yaptıklarını bilmiyoruz ve en kötüsünü almalıyız.
Ole Tange,

Sooo ... daha iyi bir örnek komut ile geleceksin, değil mi? Basit bir düzenlemenin sorunu çözmediği yerlerden biri mi? İyi bir soru soruyorsunuz ve cevaplandığını görmek isterim, ancak "bunu yapma, o zaman" makul bir cevapsa, cevap alma ihtimaliniz daha düşüktür.
Warren Young,

Oh bu arada ... Yapma;)
Tim

Soruda belirtildiği gibi: "" "Yukarıdakilerde" sleep 1000; echo f "kullanıyorum, ancak gerçekte kullanıcı tarafından sağlanan, bu nedenle" "" herhangi bir şey içerebilir
23'da Ole Tange

Yanıtlar:


10

Kısa cevap:

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

ve programı CTRL + N ile durdurun.

Uzun açıklama:

  1. Sunucunuzu veya yerel kesme karakterini birbiriyle çarpışmaması için değiştirmek için bu sttyseçeneği kullanmalısınız . Yukarıdaki komutta sunucu kesme karakterini CTRL + N olarak değiştirdim. Yerel kesme karakterinizi değiştirebilir ve sunucunun karakterini hiçbir değişiklik yapmadan bırakabilirsiniz.intr
  2. Kesme karakterinin çıktınızda (ve diğer kontrol karakterlerinde) olmasını istemiyorsanız, kullanın stty -echoctl.
  3. Kontrol karakterlerinin sshd tarafından başlatılan sunucuda açık olduğundan emin olmalısınız. Yapmazsanız, oturumu kapattıktan sonra hala takılmaya devam eden işlemlerle başlayabilirsiniz.stty isig
  4. Aslında boş ifadeyle SIGINTsinyal alıyorsunuz trap '/bin/true' SIGINT. Tuzak olmadan ucunda SIGINT sinyalinden sonra herhangi bir stdout olmaz.

İkilik girdilerle iyi bir şekilde ilgilenmiyor gibi görünüyor: seq 1000 | gzip | ssh -t -t sunucusu "stty isig intr ^ N - echoctl; trap '/ bin / true' SIGINT; uyku 1; zcat | bzip2" | bzcat> foo;
Ole Tange

Konsoldan sonra başka bir şey için ssh için standart girdi ayarladıysanız konsoldan kesemezsiniz. Bu durumda stdin akımı tarafından kesilmelidir.
digital_infinity

Bunun seq 1000 | gzip | ssh -tt dell-test "zcat|bzip2" | bzcat > fooda işe yaramadığını öğrendim . Bu komut çalışmasını yapabilmek için kaldırmamız gerekiyor -tt. Yani sözde terminal tahsisi muhtemelen stdin'den bir girdi alır
digital_infinity

Uuencode'u denedim. Bu versiyonda çalışmıyor: cat foo.gz | perl -ne 'baskı paketi ("u", $ _)' | ssh -t -t sunucu 'perl -ne "baskı açma (\" u \ ", \ $ _)" | zcat | gzip | perl -ne "baskı paketi (\" u \ ", \ $ _)" '| perl -ne 'print unpack ("u", $ _)'>> foo2.gz
Ole Tange

1
Bu var: (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. Kesme karakteri çalışmıyor olsa da - stdin meşgulken kesme karakteri için bir iletim yöntemine ihtiyacımız var .
digital_infinity

3

Tüm çözümleri denedim ve bu en iyisiydi:

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


Bu sleepbağlantının kesilmesi durumunda işlemi durdurmaz .
16'da

Bağlantı koptuğunda stdin, işlem grubunu öldürecek olan kedinin engellenmesinden kopar. Bu INTerrupt sinyalinin göreviniz için yeterince iyi olup olmadığı farklı bir sorudur.
Eric Woodruff

Bunun için yeterince iyi sleepolmalı, değil mi? Bazı ekledik date >> /tmp/killedsonra cat, ancak tetiklenir değildi. İlgili bir zaman aşımı var mı? Zsh'yi normal kullanıyorum, ancak uzak oturum açma kabuğu olarak bash ile de test ettim.
blueyed

Bence bağlantı zaman aşımının insafına kalmışsın.
Eric Woodruff

Bunu kontrol etmek için ayarlar var mı? İstemci tarafı -o ServerAliveInterval=3 -o ServerAliveCountMax=2için hızlı bir şekilde tespit edilmesini sağlar, ancak sunucu tarafı için bir şey var mı?
16'da

2

Sanırım sunucuda çalıştırdığınız işlemin PID'sini bulabilir ve başka bir sshkomut kullanarak bir sinyal gönderebilirsiniz (şunun gibi:) ssh server "kill -2 PID".

Farklı bir makinede çalışan uygulamalara yeniden yapılandırma sinyalleri göndermek için bu yöntemi kullanıyorum (uygulamalarım SIGUSR1'i yakaladı ve bir yapılandırma dosyası okudu). Benim durumumda PID bulmak kolaydır, çünkü benzersiz işlem isimlerim var ve PID'yi bir psistek göndererek bulabilirim ssh.


Uzaktan çalıştırılan programın PID'sini bulmanın kurşun geçirmez bir yolunu görmüyorum. Unutmayın, kullanıcı tarafından verilir. Şunlar olabilir: ssh server 'exec $ (echo fyrrc 1000 | / usr / games / rot13)'
Ole Tange

1

Çözüm http://www.gnu.org/software/parallel/parallel_design.html#Remote-Ctrl-C- ve- standard-error-stderr 'e dönüştü.

$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

----- yerel terminalde

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

Merhaba! Sanırım, nasıl çalıştığını, nasıl çalıştığını ayrıntılı olarak açıklayarak, cevabınızı çok daha kullanışlı hale getirebileceğinizi düşünüyorum. Yeni bilgiler eklemek için düzenlemekten çekinmeyin.
dhag,
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.