2013-04-02 3 views
6

में लिनक्स कमांड आउटपुट स्ट्रिंग और आउटपुट स्थिति कैसे प्राप्त करें मैं एक लिनक्स कमांड की आउटपुट स्ट्रिंग के साथ-साथ सी ++ प्रोग्राम में कमांड आउटपुट स्थिति प्राप्त करना चाहता हूं। मैं अपने आवेदन में लिनक्स कमांड निष्पादित कर रहा हूं।सी ++

उदाहरण के लिए

: कमान:

rmdir ABCD

कमान उत्पादन स्ट्रिंग:

rmdir: ऐसी कोई फ़ाइल या निर्देशिका

: `एबीसीडी 'को दूर करने में विफल रहा है

कमांड सेंट atus:

1 (आदेश में विफल रहा है कर दिया गया है जिसका मतलब है)

मैं लिनक्स समारोह system() जो उत्पादन का दर्जा देता है, और समारोह popen() जो मुझे एक कमांड के उत्पादन में स्ट्रिंग देता है उपयोग करने की कोशिश, लेकिन न तो समारोह मुझे लिनक्स कमांड की आउटपुट स्ट्रिंग और आउटपुट स्थिति दोनों देता है।

+1

सी ++ का उपयोग कर रहे सवाल को सी टैग क्यों किया गया है? –

उत्तर

7

आउटपुट स्ट्रिंग मानक आउटपुट या मानक त्रुटि वर्णनकर्ता (क्रमशः 1 या 2) में है।

आप इन धाराओं रीडायरेक्ट करने के लिए एक जगह है, जहाँ आप उन्हें (- एक POSIX pipe उदाहरण के लिए) पढ़ सकते हैं करने के लिए (dup और dup2 समारोह पर एक नज़र डालें)। (का एक हिस्सा)

int pd[2]; 
int retValue; 
char buffer[MAXBUF] = {0}; 
pipe(pd); 
dup2(pd[1],1); 
retValue = system("your command"); 
read(pd[0], buffer, MAXBUF); 

अब, आप बफर में अपने उत्पादन और retValue में वापसी कोड:

सी में मैं इस तरह कुछ करना चाहते हैं।

वैकल्पिक रूप से, आप exec (अर्थात execve) से एक समारोह का उपयोग कर सकते हैं और wait या waitpid साथ वापसी मान मिलता है।

अद्यतन: यह केवल मानक आउटपुट को पुनर्निर्देशित करेगा। मानक त्रुटि को पुनर्निर्देशित करने के लिए, dup2(pd[1],1) का उपयोग करें।

+0

क्या आप वाकई यह काम करते हैं? मैंने सोचा कि 'सिस्टम()' तब तक वापस नहीं आता जब तक कि खोल प्रक्रिया समाप्त नहीं हो जाती। इसके अलावा, अगर बच्चे का उत्पादन बड़ा होता है तो 'stdout' को लिखना ब्लॉक हो सकता है, जिससे डेडलॉक हो सकता है। मुझे लगता है कि अगर यह काम करता है तो मैं आश्चर्यचकित नहीं होगा क्योंकि बच्चा बाहर निकलने पर डेटा पहले ही पाइप में है, लेकिन फिर भी डेडलॉक एक मुद्दा हो सकता है। – FatalError

+0

ठीक है, यह आउटपुट का आकार पाइप के आकार से बड़ा है (मेरी मशीन पर डिफ़ॉल्ट रूप से 65536)। यदि इसकी अपेक्षा की जाती है, तो फोर्क + exec पसंदीदा तरीका है। लेकिन अगर नहीं (मेरा मतलब है, अगर मामला ज्ञात है और आउटपुट आकार बाध्य है), परेशान क्यों? :) –

+0

निश्चित रूप से, काफी उचित है। दिलचस्प रणनीति के लिए +1 – FatalError

2

दुर्भाग्यवश ऐसा करने के लिए लिनक्स पर सी में कोई आसान और आसान तरीका नहीं है। Here's एक उदाहरण है कि बच्चे की प्रक्रिया के stdout/stderr/stdin को सही तरीके से कैसे पढ़/लिखना है।

और जब आप बाहर निकलें कोड प्राप्त करना चाहते हैं आप waitpid उपयोग करने के लिए (पूर्ण उदाहरण प्रदान की पृष्ठ के निचले भाग पर प्रदान की जाती है) है:

endID = waitpid(childID, &status, WNOHANG|WUNTRACED); 

अब आप सिर्फ एक साथ

उन दो में शामिल होने :) है

वहाँ भी एक महान मुक्त पुस्तक नामित एक dvanced एल inux पी rogramming (एएलपी) के बारे में विस्तृत जानकारी युक्त है here उपलब्ध समस्या के प्रकार।

+0

और वहाँ इन मुद्दों –

+0

@BasileStarynkevitch आह, एएलपी पर http://advancedlinuxprogramming.com/ में एक पूरा अध्याय है, इसके बारे में पूरी तरह से भूल गया ... मैंने इसे जवाब देने के लिए जोड़ा है। – Vyktor

3

सरल समाधान system उपयोग करने के लिए, और एक अस्थायी रूप से फ़ाइल है, जो आपको बाद में नष्ट कर सकते हैं के लिए बाहर मानक और मानक त्रुटि पुनर्निर्देशित करना होता है।

0

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

char buffer[MAXBUF] = {0}; 
    FILE *fd = popen("openssl version -v", "r"); 
    if (NULL == fd) 
    { 
     printf("Error in popen"); 
     return; 
    } 
    fread(buffer, MAXBUF, 1, fd); 
    printf("%s",buffer); 

    pclose(fd); 

अधिक जानकारी के लिए popen के लिए man पृष्ठ पढ़ें।

1

बिल्डिंग पायोत्र Zierhoffer पर ऊपर का जवाब, यहाँ एक समारोह है कि सिर्फ इतना है कि करता है, और यह भी stdout पुनर्स्थापित करता है और अपनी मूल स्थिति stderr।

// Execute command <cmd>, put its output (stdout and stderr) in <output>, 
// and return its status 
int exec_command(string& cmd, string& output) { 
    // Save original stdout and stderr to enable restoring 
    int org_stdout = dup(1); 
    int org_stderr = dup(2); 

    int pd[2]; 
    pipe(pd); 

    // Make the read-end of the pipe non blocking, so if the command being 
    // executed has no output the read() call won't get stuck 
    int flags = fcntl(pd[0], F_GETFL); 
    flags |= O_NONBLOCK; 

    if(fcntl(pd[0], F_SETFL, flags) == -1) { 
     throw string("fcntl() failed"); 
    } 

    // Redirect stdout and stderr to the write-end of the pipe 
    dup2(pd[1], 1); 
    dup2(pd[1], 2); 
    int status = system(cmd.c_str()); 
    int buf_size = 1000; 
    char buf[buf_size]; 

    // Read from read-end of the pipe 
    long num_bytes = read(pd[0], buf, buf_size); 

    if(num_bytes > 0) { 
     output.clear(); 
     output.append(buf, num_bytes); 
    } 

    // Restore stdout and stderr and release the org* descriptors 
    dup2(org_stdout, 1); 
    dup2(org_stderr, 2); 
    close(org_stdout); 
    close(org_stderr); 

    return status; 
}