मैं एक टर्मिनल को एक अलग प्रक्रिया में कैसे संलग्न करूं?


98

मैंने अपने टर्मिनल से इस तरह एक प्रक्रिया को अलग कर लिया है:

$ process &

वह टर्मिनल अब लंबे समय से बंद है, लेकिन processअभी भी चल रहा है, और मैं उस प्रक्रिया के स्टडिन को कुछ कमांड भेजना चाहता हूं। क्या यह संभव है?



1
के लिए खोज retty, neercsआदि और यह भी देखने serverfault.com/questions/24425 , serverfault.com/questions/115998
गाइल्स

जवाबों:


112

हाँ यही है। सबसे पहले, एक पाइप बनाएं mkfifo /tmp/fifo:। प्रक्रिया में संलग्न करने के लिए gdb का उपयोग करें: gdb -p PID

फिर नज़दीकी स्टडिन call close (0):; और इसे फिर से खोलें:call open ("/tmp/fifo", 0600)

अंत में, दूर लिखें (एक अलग टर्मिनल से, जैसा कि gdb शायद लटकाएगा):

echo blah > /tmp/fifo


6
बहुत प्रभावशाली!
सैमुअल एडविन वार्ड

1
क्या मैं किसी फ़ाइल पर रीडायरेक्ट प्रक्रिया के समान कुछ कर सकता हूँ?
रस्टीक्स

@rustyx: untested है, लेकिन यह काम करना चाहिए: एक पाइप एक फ़ाइल के बजाय बनाने के लिए, touch /tmp/thefile। स्टडआउट 1 है, इसलिए call close (1); इसके अलावा, लिखने के लिए सही अनुमतियों का उपयोग करें call open ("/tmp/thefile", 0400):। echo…है, जाहिर है, की जरूरत नहीं।
अंसगर एज़्टरमैन

यह भी खूब रही! मैं कुछ प्रक्रियाओं के लिए "y" या "n" प्रतिक्रियाओं को भेजने के लिए इसका उपयोग कर रहा हूं जिन्हें पूरी तरह से अलग कर दिया गया है। अलग की गई प्रक्रिया में एक अलग विंडो में उसका स्टडआउट है। जब मैं इस ट्रिक को करता हूं, तो मैं यह देख सकता हूं कि जैसे ही यह गूंजता है, मुझे "y" या 'n' प्राप्त नहीं होता है, मुझे gdb छोड़ना चाहिए और इसे अलग करना चाहिए और फिर इसे तदनुसार सभी इको प्राप्त होते हैं, इसलिए प्रक्रिया से पंद्रहवें इनपुट प्राप्त होने से पहले gdb छोड़ने की आवश्यकता के बिना प्रदर्शन करने का एक तरीका है?
krb686

दुर्भाग्य से यह सिर्फ लटका हुआ लगता है call open("/tmp/fifo", 0600)। किसी भी मदद की बहुत सराहना की जाएगी
आर्चर

27

जब मूल टर्मिनल अब सुलभ नहीं है ...

reptyrहो सकता है कि आप क्या चाहते हों, https://serverfault.com/a/284795/187998 देखें

वहां से बोली:

रेप्टियर पर एक नज़र डालें , जो वास्तव में ऐसा ही करता है। Github पेज पर सारी जानकारी है।

reptyr - "री-पाइटिंग" कार्यक्रमों के लिए एक उपकरण।

reptyr एक मौजूदा चल रहे कार्यक्रम को लेने और इसे एक नए टर्मिनल में संलग्न करने के लिए एक उपयोगिता है। Ssh पर एक लंबी-चलने वाली प्रक्रिया शुरू की, लेकिन इसे छोड़ना होगा और इसे बाधित नहीं करना चाहिए? बस एक स्क्रीन शुरू करें, इसे हथियाने के लिए reptyr का उपयोग करें, और फिर ssh सत्र और घर पर सिर को मारें।

उपयोग

reptyr पीआईडी

"रेप्टियर पीआईडी" आईडी पीआईडी ​​के साथ प्रक्रिया को पकड़ लेगा और इसे आपके वर्तमान टर्मिनल से जोड़ देगा।

संलग्न करने के बाद, प्रक्रिया इनपुट से नए टर्मिनल में आउटपुट लिख देगी, जिसमें ^ C और ^ Z शामिल हैं। (दुर्भाग्य से, यदि आप इसे पृष्ठभूमि में रखते हैं, तो आपको अभी भी पुराने टर्मिनल में "बीजी" या "एफजी" चलाना होगा। यह आपके शेल को पैच किए बिना एक उचित तरीके से ठीक करने की संभावना है।)


12

मुझे पूरा यकीन है कि आप नहीं कर सकते।

का उपयोग कर की जाँच करें ps x। एक प्रक्रिया एक है, तो ?के रूप में नियंत्रित करने tty , तुम नहीं इनपुट इसे करने के लिए किसी भी अधिक भेज सकते हैं।

9942 ?        S      0:00 tail -F /var/log/messages
9947 pts/1    S      0:00 tail -F /var/log/messages

इस उदाहरण में, आप 9947कुछ ऐसा करने के लिए इनपुट भेज सकते हैं echo "test" > /dev/pts/1। अन्य प्रक्रिया ( 9942) उपलब्ध नहीं है।

अगली बार, आप इस स्थिति से बचने के लिए स्क्रीन या tmux का उपयोग कर सकते हैं ।


5
या dtachअगर आपको पूरी जरूरत नहीं है screen
मैनटवर्क

4
मानकों (इसे POSIX, SUS) में कोई तरीका नहीं है, लेकिन कई (सबसे?) सिस्टम पर यह है तंत्र उपयोग डिबगर का उपयोग कर संभव। अंसार का जवाब देखिए । इसके साथ rootआप अन्य उपयोगकर्ता की प्रक्रियाओं के लिए भी ऐसा कर सकते हैं।
dmckee

3
कर echo "test" > /dev/pts/1प्रक्रिया के लिए इनपुट नहीं भेजेंगे 9947- यह उत्पादन शब्द "परीक्षण" है कि इस प्रक्रिया के टर्मिनल पर होगा।
भजन

6

संपादित करें : जैसा कि स्टीफ़न Gimenez ने कहा, यह इतना आसान नहीं है। यह केवल आपको एक अलग टर्मिनल पर प्रिंट करने की अनुमति देता है।

आप / प्रक्रिया का उपयोग करके इस प्रक्रिया को लिखने का प्रयास कर सकते हैं । यह / proc / pid / fd / 0 में स्थित होना चाहिए , इसलिए एक सरल:

echo "hello" > /proc/PID/fd/0

करना चाहिए। मैंने इसे करने की कोशिश नहीं की है, लेकिन यह काम करना चाहिए, जब तक कि इस प्रक्रिया में अभी भी एक वैध स्टडिन फाइल डिस्क्रिप्टर है। आप इसके साथ जांच कर सकते हैं ls -lपर / proc / पीआईडी / fd /

  • यदि यह / dev / null => का लिंक है तो यह बंद हो गया है
  • यदि यह / dev / pts / X या सॉकेट के लिए एक लिंक है => यह खुला है

प्रक्रियाओं को चालू रखने के तरीके के बारे में अधिक जानकारी के लिए नोह को देखें ।


2
यह इतना आसान नहीं है। उदाहरण के लिए, यदि स्टड एक टर्मिनल से जुड़ा हुआ है, echoतो टर्मिनल डिवाइस पर कुछ आईएनजी बस प्रिंट करेगा जो आपने टर्मिनल पर लिखा था, यह प्रक्रिया को प्रेषित नहीं किया जाएगा।
स्टेफेन जिमेनेज

5

बस के साथ कमांड लाइन को समाप्त &करने से प्रक्रिया पूरी तरह से अलग नहीं होगी, यह सिर्फ पृष्ठभूमि में चलेगी। ( zshआप &!वास्तव में इसे अलग करने के लिए उपयोग कर सकते हैं , अन्यथा आप disownइसे बाद में कर सकते हैं)।

जब कोई प्रक्रिया पृष्ठभूमि में चलती है, तो वह अपने नियंत्रण टर्मिनल से अब इनपुट प्राप्त नहीं करेगी। लेकिन आप इसे वापस अग्रभूमि में भेज सकते हैं fgऔर फिर यह फिर से इनपुट पढ़ेगा।

अन्यथा, बाहरी रूप से इसके फ़ाइसेस्क्रिप्ट्स (स्टड सहित) को बदलना या खोए हुए नियंत्रण टर्मिनल को फिर से जोड़ना संभव नहीं है ... जब तक कि आप डिबगिंग टूल का उपयोग नहीं करते हैं ( अंसार का जवाब देखें , या rettyकमांड पर एक नज़र डालें )।


और यहाँ एक संबंधित प्रश्न है: unix.stackexchange.com/q/17648/9426
स्टीफन

@ रागच ने कहा "वह टर्मिनल अब बंद हो गया है"।
andcoz

1
@andcoz: हाँ, लेकिन वह भाग्यशाली रहा है कि इस कार्यक्रम को शटअप नहीं किया गया है। मैं एक सुरक्षित तरीका सुझा रहा था।
स्टीफन जिमेनेज

यहाँ, केवल तभी काम करता है जब मैं पहली बार अनुप्रेषित करता हूं जैसे कि >>/dev/stderr, अन्यथा, जब मैं टर्मिनल बंद करता हूं, तो "विघटित" प्रक्रिया भी समाप्त हो जाएगी .. मैं वास्तव में इस थियो को कभी नहीं समझ पाया ..
कुंभ राशि
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.