आदेश पंक्ति का उपयोग करके, प्रारंभ की गई प्रक्रिया के बारे में पुनर्निर्देशित STDERR / STDOUT?


127

शेल में आप पुनर्निर्देशन > <आदि कर सकते हैं , लेकिन एक कार्यक्रम शुरू करने के बारे में कैसे?

यहां बताया गया है कि मैं यह सवाल पूछने कैसे आया, मेरे टर्मिनल की पृष्ठभूमि में चलने वाला एक कार्यक्रम कष्टप्रद पाठ का उत्पादन करता रहता है। यह एक महत्वपूर्ण प्रक्रिया है इसलिए मुझे पाठ से बचने के लिए एक और खोल खोलना होगा। मैं >/dev/nullकुछ अन्य पुनर्निर्देशन में सक्षम होना चाहूंगा ताकि मैं एक ही शेल में काम कर सकूं।


मुझे पता है कि STDOUT / STDERR को रीडायरेक्ट करने का सबसे आसान तरीका है DUP2 को उनके फ़ाइल डिस्क्रिप्टर BEFORE फोर्किंग के लिए। यह एक काफी मानक अभ्यास है, और शायद जिस तरह से गोले अभी इसे पूरा करते हैं। यकीन नहीं है कि अगर एक जवाब देता है, लेकिन मुझे लगता है कि यह वहाँ एक अच्छा होने की संभावना कम कर देता है।
स्टीफन माई

जवाबों:


124

आपके ट्टी को बंद करने और फिर से खोलने का छोटा (यानी लॉग ऑफ और बैक, जो प्रक्रिया में आपकी कुछ पृष्ठभूमि प्रक्रियाओं को भी समाप्त कर सकता है) आपके पास केवल एक विकल्प बचा है:

  • gdb का उपयोग करके प्रक्रिया में संलग्न करें, और चलाएँ:
    • पी डुप 2 (खुला ("/ देव / नल", 0), 1)
    • पी डुप 2 (खुला ("/ देव / नल", 0), 2)
    • अलग करें
    • छोड़ना

उदाहरण के लिए:

$ tail -f /var/log/lastlog &
[1] 5636

$ ls -l /proc/5636/fd
total 0
lrwx------ 1 myuser myuser 64 Feb 27 07:36 0 -> /dev/pts/0
lrwx------ 1 myuser myuser 64 Feb 27 07:36 1 -> /dev/pts/0
lrwx------ 1 myuser myuser 64 Feb 27 07:36 2 -> /dev/pts/0
lr-x------ 1 myuser myuser 64 Feb 27 07:36 3 -> /var/log/lastlog

$ gdb -p 5636
GNU gdb 6.8-debian
Copyright (C) 2008 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Attaching to process 5636
Reading symbols from /usr/bin/tail...(no debugging symbols found)...done.
Reading symbols from /lib/librt.so.1...(no debugging symbols found)...done.
Loaded symbols for /lib/librt.so.1
Reading symbols from /lib/libc.so.6...(no debugging symbols found)...done.
Loaded symbols for /lib/libc.so.6
Reading symbols from /lib/libpthread.so.0...(no debugging symbols found)...done.
[Thread debugging using libthread_db enabled]
[New Thread 0x7f3c8f5a66e0 (LWP 5636)]
Loaded symbols for /lib/libpthread.so.0
Reading symbols from /lib/ld-linux-x86-64.so.2...(no debugging symbols found)...done.
Loaded symbols for /lib64/ld-linux-x86-64.so.2

(no debugging symbols found)
0x00007f3c8eec7b50 in nanosleep () from /lib/libc.so.6

(gdb) p dup2(open("/dev/null",0),1)
[Switching to Thread 0x7f3c8f5a66e0 (LWP 5636)]
$1 = 1

(gdb) p dup2(open("/dev/null",0),2)
$2 = 2

(gdb) detach
Detaching from program: /usr/bin/tail, process 5636

(gdb) quit

$ ls -l /proc/5636/fd
total 0
lrwx------ 1 myuser myuser 64 Feb 27 07:36 0 -> /dev/pts/0
lrwx------ 1 myuser myuser 64 Feb 27 07:36 1 -> /dev/null
lrwx------ 1 myuser myuser 64 Feb 27 07:36 2 -> /dev/null
lr-x------ 1 myuser myuser 64 Feb 27 07:36 3 -> /var/log/lastlog
lr-x------ 1 myuser myuser 64 Feb 27 07:36 4 -> /dev/null
lr-x------ 1 myuser myuser 64 Feb 27 07:36 5 -> /dev/null

आप इस पर भी विचार कर सकते हैं:

  • का उपयोग कर screen; स्क्रीन कई वर्चुअल TTY प्रदान करता है जिन्हें आप नए SSH / telnet / etc, सत्रों को खोलने के बिना स्विच कर सकते हैं
  • का उपयोग कर nohup; यह आपको ... प्रक्रिया में किसी भी पृष्ठभूमि प्रक्रिया को खोए बिना अपने सत्र को बंद करने और फिर से खोलने की अनुमति देता है।

1
आपके gdb उत्तर ने टेल -f फ़ाइल के साथ काम नहीं किया, और इसने c-gd-bddb के साथ संकलित किए गए c में परीक्षण कार्यक्रम के साथ काम नहीं किया जो हर सेकंड एक प्रिंटफ करता है। इसके अलावा cont अधिक gdb कमांड को रन करना असंभव बनाता है, कमांड को अलग किया जाएगा, फिर छोड़ दिया जाएगा।
इयान किलिंग

अलग करने के बारे में सही, यह 2AM है। :) क्या वास्तव में gdb समाधान के साथ काम नहीं किया?
vladr

12
यदि आप stdout / stderr (जाहिरा तौर पर / dev / null के अलावा कुछ भी) को रीडायरेक्ट कर रहे हैं, तो आपको फ़ाइल को लिखने की पहुँच के साथ खोलने की आवश्यकता है - open("/path/to/new/stdout",O_WRONLY)। O_Wronly शायद उपलब्ध नहीं होगा, हालांकि; इसका मूल्य 1Linux / glibc पर है।
जैंडर

13
सावधानी का एक शब्द: gdb में एक प्रक्रिया के साथ संलग्न करना प्रक्रिया को रोक देता है जब तक आप इससे अलग नहीं हो जाते।
मार्टी बी

1
@Jander की टिप्पणी पर जोड़ते हुए, इसके अलावा 1025सक्रियण का उपयोग करते हुए , जो कि अगर आप एक ही फाइल में stderr और stdout दोनों को रीडायरेक्ट करते हैं, तो यह आसान है। O_APPENDO_WRONLY
10

57

इससे चल जाएगा:

strace -ewrite -p $PID

यह साफ नहीं है (जैसे लाइनें दिखाता है:) write(#,<text you want to see>), लेकिन काम करता है!


आप इस तथ्य को भी नापसंद कर सकते हैं कि तर्क संक्षिप्त हैं। नियंत्रित करने के लिए उस -sपैरामीटर का उपयोग करें जो प्रदर्शित स्ट्रिंग की अधिकतम लंबाई निर्धारित करता है।

यह सभी धाराओं को पकड़ता है, इसलिए आप इसे किसी भी तरह से फ़िल्टर करना चाहते हैं:

strace -ewrite -p $PID 2>&1 | grep "write(1" 

केवल वर्णनकर्ता 1 कॉल दिखाता है। 2>&1STDERR को STDOUT पर पुनर्निर्देशित करना है, जैसा straceकि डिफ़ॉल्ट रूप से STDERR को लिखना है।


6
यह वह नहीं है जो ओपी ने मांगा था। ओपी ने टीटीवाई से दूर करने के लिए कहा, अवरोधन नहीं। इसके अलावा, कुछ प्लेटफार्मों पर स्ट्रेस / ट्रस इंटरसेप्टेड स्ट्रीम कैरेक्टर्स और / या नॉन-एएससीआईआई से बचने के बीच स्पेस डालेगा, और आपको उन प्रोसेसिंग से भी निपटना होगा।
vladr

4
हां, यह बात आंशिक रूप से होती है - लेकिन कुछ लोगों के लिए यह प्रश्न पढ़ने के लिए यह सब उनकी ज़रूरत है - यह देखने के लिए कि क्या हो रहा है एक कार्यक्रम में गलती से नल या किसी अन्य कंसोल पर लिखने के लिए चलाएं। मैं इस प्रक्रिया में इस सवाल को खोजने के बाद पता चला और सोचा कि यह एक अच्छा हैक है (कम से कम मेरे लिए)। और काफी लोगों को यह मददगार लगता है अगर मेरी आँखें मुझे दूर न करें;)
नौगटूर

यह भी संभव है कि sudoइसकी आवश्यकता है।
बृहस्पतिवार

21

vladr (और अन्य ') उत्कृष्ट अनुसंधान:

एक ही निर्देशिका में निम्नलिखित दो फाइलें बनाएं, आपके रास्ते में कुछ, $ HOME / बिन कहें:

silence.gdb, युक्त (vladr के उत्तर से):


p dup2(open("/dev/null",0),1)
p dup2(open("/dev/null",0),2)
detach
quit

और मौन, युक्त:


#!/bin/sh
if [ "$0" -a "$1" ]; then
 gdb -p $1 -x $0.gdb
else
 echo Must specify PID of process to silence >&2
fi

chmod +x ~/bin/silence  # make the script executable

अब, अगली बार जब आप फ़ायरफ़ॉक्स को रीडायरेक्ट करना भूल जाते हैं, उदाहरण के लिए, और आपका टर्मिनल अपरिहार्य हो जाता है "


ps  # look for process xulrunner-stub (in this case we saw the PID in the error above)
silence 5117  # run the script, using PID we found

अगर आप इसे देखना नहीं चाहते हैं तो आप gdb के आउटपुट को / dev / null में रीडायरेक्ट कर सकते हैं।


3
मेरे gdb (v7.2) में एक आसान विकल्प है --batch-silentजो आउटपुट को दबाता है और अगर कुछ गलत हो जाता है (जैसे गुम प्रक्रिया) तो आपको gdb कंसोल में डंप नहीं करता है। BTW, $!सबसे हाल की पृष्ठभूमि की नौकरी को संदर्भित करता है, लेकिन मुझे नहीं लगता कि इसका उपयोग स्क्रिप्ट में ही किया जा सकता है। मैं एक उपनाम का उपयोग करता हूं: alias silencebg='silence $!'
seanf

18

एक रनिंग प्रोसेस से दूसरे टर्मिनल, फ़ाइल या स्क्रीन पर आउटपुट पुनर्निर्देशित करें:

tty
ls -l /proc/20818/fd
gdb -p 20818

जीडीबी के अंदर :

p close(1)
p open("/dev/pts/4", 1)
p close(2)
p open("/tmp/myerrlog", 1)
q

बैश टर्मिनल से एक चल रही प्रक्रिया को अलग करें और इसे जीवित रखें:

[Ctrl+z]
bg %1 && disown %1
[Ctrl+d]

स्पष्टीकरण:

20818 - सिर्फ रनिंग प्रोसेस pid
p का एक उदाहरण - gdb कमांड का प्रिंट रिजल्ट
क्लोज (1) - क्लोज्ड स्टैंडर्ड आउटपुट
/ dev / pts / 4 - टर्मिनल
क्लोज टू राइट टू (2) - क्लोज एरर आउटपुट
/ tmp / myerrlog - फाइल
q को लिखें - gdb
bg% 1 छोड़ें - पृष्ठभूमि पर
% 1 पर रोक काम चलाएं 1 - टर्मिनल से अलग नौकरी 1


2
यह काम नहीं करेगा यदि stdin(फाइल डिस्क्रिप्टर 0) बंद है।
पाबूक

इससे मेरा दिन बच गया। मेरे पास पहले 10% के लिए एक घंटे लेने वाले ssl-session में रनिंग मेक था और मैं वास्तव में अपने लैपटॉप को एक और 10 घंटे तक चालू नहीं रखना चाहता था। लेकिन क्या मुझे सही मान लेना चाहिए कि आपके लिए रीडायरेक्ट रीडर को पढ़ना चाहिए p open("/tmp/myerrlog", 2)?
गेरार्डवी

CentOS 6 पर चलने के साथ एक बहुत ही मामूली समस्या थी - फ़ाइल "/ tmp / myerrlog" पहले से मौजूद थी। यह निश्चित रूप से स्पर्श के साथ बनाने के लिए तुच्छ था।
Ebneter

3

आपके प्रश्न का सीधा उत्तर नहीं है, लेकिन यह एक ऐसी तकनीक है जिसे मैं पिछले कुछ दिनों से उपयोगी पा रहा हूं: 'स्क्रीन' का उपयोग करके प्रारंभिक कमांड चलाएँ, और फिर अलग करें।


2

यह पिछले उत्तर के आधार पर स्क्रिप्ट भाग है, जो एक खुली प्रक्रिया के निष्पादन के दौरान लॉग फ़ाइल को रीडायरेक्ट करता है, इसे प्रक्रिया में पोस्टस्क्रिप्ट के रूप में उपयोग किया जाता logrotateहै

#!/bin/bash

pid=$(cat /var/run/app/app.pid)
logFile="/var/log/app.log"

reloadLog()
{
    if [ "$pid" = "" ]; then
        echo "invalid PID"
    else
        gdb -p $pid >/dev/null 2>&1 <<LOADLOG
p close(1)
p open("$logFile", 1)
p close(2)
p open("$logFile", 1)
q
LOADLOG
        LOG_FILE=$(ls /proc/${pid}/fd -l | fgrep " 1 -> " | awk '{print $11}')
        echo "log file set to $LOG_FILE"
    fi
}

reloadLog

1

दोहराव मानक आउटपुट / इनपुट / पहले से चल रही प्रक्रिया की त्रुटि को पुन: निर्देशित करने के लिए एक सरल * निक्स उपयोगिता है।

https://www.isi.edu/~yuri/dupx/


0

आप reredirect ( https://github.com/jerome-pouiller/reredirect/ ) का उपयोग कर सकते हैं ।

प्रकार

reredirect -m FILE PID

और आउटपुट (मानक और त्रुटि) फ़ाइल में लिखा जाएगा।

पुनर्निर्देशित README यह भी बताता है कि प्रक्रिया की मूल स्थिति को कैसे पुनर्स्थापित किया जाए, कैसे किसी अन्य कमांड पर पुनर्निर्देशित किया जाए या केवल stdout या stderr को पुनर्निर्देशित किया जाए।

reredirectएक स्क्रिप्ट भी प्रदान करता है जिसे relinkवर्तमान टर्मिनल पर पुनर्निर्देशित करने की अनुमति मिलती है:

relink PID
relink PID | grep usefull_content

(पुनर्निर्देशित में एक और उत्तर में वर्णित डुप्क्स की तुलना में समान विशेषताएं हैं लेकिन, यह Gdb पर निर्भर नहीं करता है)।

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