ssh -t पर stderr


11

यह STDERR को आउटपुट भेजता है, लेकिन Ctrl+ प्रचार नहीं करता है C(यानी Ctrl+ Cमार डालेगा sshलेकिन रिमोट नहीं sleep):

$ ssh localhost 'sleep 100;echo foo ">&2"'

यह Ctrl+ C(यानी Ctrl+ Cमार डालेगा sshऔर रिमोट sleep) को प्रचारित करेगा , लेकिन STDERR को STDOUT में भेजता है:

$ ssh -tt localhost 'sleep 100;echo foo ">&2"'

मैं दूसरे को STDERR आउटपुट STDERR भेजने के लिए कैसे बाध्य कर सकता हूं, जबकि अभी भी Ctrl+ प्रचार कर रहा है C?

पृष्ठभूमि

जीएनयू समानांतर Ctrl+ 'ssh -tt' का उपयोग करता है प्रचार करने के लिए + C। इससे दूरस्थ रूप से चलने वाली नौकरियों को मारना संभव हो जाता है। लेकिन STDERR को भेजे गए डेटा को प्राप्त अंत में STDERR पर जाना जारी रखना चाहिए।

जवाबों:


5

मुझे नहीं लगता कि आप इसके आसपास पहुँच सकते हैं।

के साथ -tt, sshdएक छद्म टर्मिनल को जन्म देता है और दास को दूरस्थ कमांड को निष्पादित करने वाले शेल के स्टड, स्टडआउट और स्टेडर बनाता है।

sshdपढ़ता है कि इसके (एकल) fd से छद्म टर्मिनल के मास्टर भाग में क्या आ रहा है और sshग्राहक को (एक एकल चैनल के माध्यम से) भेजता है । Stderr के लिए कोई दूसरा चैनल नहीं है जैसा कि बिना है -t

इसके अलावा ध्यान दें कि छद्म टर्मिनल का टर्मिनल लाइन अनुशासन (और डिफ़ॉल्ट रूप से) आउटपुट को बदल सकता है। उदाहरण के लिए LF को CRLF में परिवर्तित किया जाएगा और स्थानीय टर्मिनल पर नहीं, इसलिए आप आउटपुट पोस्ट-प्रोसेसिंग को निष्क्रिय करना चाह सकते हैं।

$ ssh  localhost 'echo x' | hd
00000000  78 0a                                             |x.|
00000002
$ ssh -t localhost 'echo x' | hd
00000000  78 0d 0a                                          |x..|
00000003
$ ssh -t localhost 'stty -opost; echo x' | hd
00000000  78 0a                                             |x.|
00000002

इनपुट पक्ष पर बहुत कुछ होगा ( ^Cचरित्र की तरह जो एक संकेत का कारण होगा, लेकिन अन्य संकेत भी, गूंज और विहित मोड लाइन संपादक में शामिल सभी हैंडलिंग )।

आप संभवतः एक पेंडो में stderr को पुनर्निर्देशित कर सकते हैं और एक दूसरे का उपयोग करके इसे पुनः प्राप्त कर सकते हैं ssh:

ssh -tt host 'mkfifo fifo && cmd 2> fifo' &
ssh host 'cat fifo' >&2

लेकिन सबसे अच्छा आईएमओ -tपूरी तरह से उपयोग करने से बचना होगा । यह वास्तव में केवल एक असली टर्मिनल से इंटरैक्टिव उपयोग के लिए है।

दूरस्थ अंत कनेक्शन को बंद करने के लिए ^ C के प्रसारण पर निर्भर होने के बजाय, आप एक आवरण का उपयोग कर सकते हैं poll()जो मारे गए sshया बंद कनेक्शन का पता लगाने के लिए करता है ।

शायद ऐसा कुछ (सरलीकृत, आप कुछ त्रुटि जाँच जोड़ना चाहते हैं):

LC_HUP_DETECTOR='
  use IO::Poll;
  $SIG{CHLD} = sub {$done = 1};
  $p = IO::Poll->new;
  $p->mask(STDOUT, POLLIN);
  $pid=fork; unless($pid) {setpgrp; exec @ARGV; die "exec: $!\n"}
  $p->poll;
  kill SIGHUP, -$pid unless $done;
  wait; exit ($?&127 ? 128+($?&127) : 1+$?>>8)
' ssh host 'perl -e "$LC_HUP_DETECTOR" some cmd'

$p->mask(STDOUT, POLLIN)ऊपर मूर्खतापूर्ण लग सकता है, लेकिन यह विचार (शायद बंद कर stdout पर पाइप के पढ़ने के अंत के लिए) एक हैंग-HUP घटना के लिए इंतजार करना है। एक अनुरोधित मास्क के रूप में POLLHUP को अनदेखा किया जाता है। POLLHUP केवल लौटी हुई घटना के रूप में अर्थपूर्ण है (यह बताने के लिए कि लेखन समाप्ति बंद हो गई है)।

हमें इवेंट मास्क के लिए एक गैर-शून्य मान देना होगा। यदि हम उपयोग करते हैं 0, perlतो कॉल भी नहीं करता है poll। इसलिए यहाँ हम POLLIN का उपयोग करते हैं।

लिनक्स पर, आप जो भी अनुरोध करते हैं, अगर पाइप टूट जाता है, तो पोल () पोलरआर वापस कर देता है।

सोलारिस और फ्रीबीएसडी पर, जहां पाइप द्विदिश हैं, जब पाइप का रीडिंग एंड (जो वहां राइटिंग एंड भी है) बंद है, तो यह POLLHUP (और FreeBSD पर POLLIN) के साथ लौटता है, जहां आपको LLIN का अनुरोध करना होता है या फिर $p->poll()नहीं वापसी)।

मैं यह नहीं कह सकता कि उन तीन ऑपरेटिंग सिस्टम के बाहर यह कितना पोर्टेबल है।


मुझे आपका विचार पसंद है, लेकिन जब तक 'सेट' सेट नहीं किया जाता, तब तक मैं आपके रैपर को किसी भी सिग्नल का पता नहीं लगा सकता। यह काम करता है: parallel --tag -j1 'ssh -tt localhost perl/catch_wrap perl/catch_all_signals & sleep 1; killall -{} ssh' ::: {1..31}लेकिन '-tt' को हटा दें और फिर यह काम नहीं करता है।
ओले तांगे

@OleTange रैपर का उद्देश्य SIGHUP को दूरस्थ नौकरी में भेजना है जब ssh की मृत्यु हो जाती है (ssh कनेक्शन हैंग-अप पर)। मुझे नहीं पता कि आपका catch_all_signals क्या करता है, लेकिन यह सब मिल जाएगा कि SIGHUP और केवल ssh कनेक्शन के हटने के बाद (इसलिए यदि यह stdout पर कुछ भी प्रिंट करता है, तो आप इसे नहीं देखेंगे)।
स्टीफन चेजलस

catch_all_signals किसी फ़ाइल में सभी संकेतों को लॉग करता है, और जैसा कि उल्लेख किया गया है कि यह '-tt' के साथ काम करता है, लेकिन इसके बिना विफल रहता है। दूसरे शब्दों में: जब ssh की मृत्यु हो जाती है, तो उसे catch_wrap से SIGHUP प्राप्त नहीं होता है।
ओले तांगे

अभी भी केवल -ttआपके संपादन के बाद काम करता है । कृपया याद रखें कि यदि आप समानांतर के माध्यम से कमांड नहीं चलाते हैं, तो ssh आपको उस टर्मिनल से वारिस करेगा जिसे आप इसे चलाते हैं।
ओले तांगे

@OleTange, मैं पुन: पेश नहीं कर सकता, यह मेरे लिए काम करता है, क्या आपने इसे मेरे द्वारा पोस्ट किए गए कोड के साथ परीक्षण किया है? कृपया अपना catch_wrap और catch_all_signals कहीं पोस्ट करें ताकि मेरी नज़र पड़ सके। इसके साथ -t, मुझे उम्मीद है कि यह काम नहीं करेगा।
स्टीफन चेज़लस

1

इसे अन्य प्लेटफार्मों पर काम करने के लिए यह अंतिम समाधान बन गया। यह जाँचता है कि क्या ssh क्लाइंट डिस्कनेक्ट हो गया है और इस तरह से पैरेंट 1 पिड हो गया है:

$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)
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.