2010-04-26 15 views
9
#!/usr/bin/env perl 
use warnings; use strict; 
use 5.012; 
use IPC::System::Simple qw(system); 

system('xterm', '-geometry', '80x25-5-5', '-bg', 'green', '&'); 

say "Hello"; 
say "World"; 

मैं पृष्ठभूमि में टर्म-कमांड चलाने के लिए इस कोशिश की, लेकिन यह काम नहीं करता:मैं पृष्ठभूमि में पर्ल सिस्टम कमांड कैसे चला सकता हूं?

कोई निरपेक्ष पथ खोल नहीं मिला: &

क्या सही होगा इसे काम करने का तरीका?

+0

का परीक्षण यहां मेरे लिए काम sorta लगता है। आप क्या खत्म करने की कोशिश कर रहे हैं? – xenoterracide

+0

क्या यह टर्मिनल खोलने वाला है और फिर टर्मिनल में हैलो वर्ल्ड प्रिंट करना है? – xenoterracide

+0

या क्या आप टर्मिनल खोलने के लिए बस एक एसिंक्रोनस कॉल करने की कोशिश कर रहे हैं? – xenoterracide

उत्तर

19

पर्ल के system समारोह दो स्वरूप हैं:

  1. एक एकल स्ट्रिंग ले रही है और कमांड खोल करने के लिए इसे पारित विशेष वर्ण संसाधित करने के लिए
  2. की एक सूची लेने के अनुमति देने के लिए स्ट्रिंग्स, पहले निष्पादित करना और शेष तारों को तर्क के रूप में गुजरना

पहले फॉर्म में आपको उन पात्रों से बचने के लिए सावधान रहना होगा जिनके लिए खोल का विशेष अर्थ हो सकता है। दूसरा रूप आम तौर पर सुरक्षित होता है क्योंकि तर्क सीधे शामिल किए जा रहे प्रोग्राम के बिना निष्पादित किए जाने वाले कार्यक्रम में पास किए जाते हैं।

आपके मामले में आप दो रूपों को मिलाकर प्रतीत होते हैं। & चरित्र का केवल "पृष्ठभूमि में इस कार्यक्रम को शुरू करने" का अर्थ है यदि यह खोल में पास हो जाता है। आपके कार्यक्रम में, एम्पर्सेंड xterm कमांड के लिए 5 वें तर्क के रूप में पारित किया जा रहा है।

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

यदि आप बहु-तर्क फ़ॉर्म का उपयोग करना पसंद करते हैं तो आपको fork() पर कॉल करना होगा और फिर system() के बजाय शायद exec() का उपयोग करना होगा।

+4

** tldr; ** 'सिस्टम ("./ script.sh $ arg1 &");' 'सिस्टम (" ./ script.sh "," $ arg1 "," &"); ' – Rombus

13

ध्यान दें कि system की सूची प्रपत्र विशेष रूप से इस तरह के & खोल मेटा-पात्रों के रूप में के रूप में नहीं इलाज वर्ण है।

perlfaq8 के जवाब से How do I start a process in the background? को


(ब्रायन डी Foy के योगदान)

वहाँ तो आप इंतजार की जरूरत नहीं है पृष्ठभूमि में कोड को चलाने के लिए एक भी तरीका नहीं है इससे पहले कि आपका प्रोग्राम अन्य कार्यों पर चलता है, इसे पूरा करने के लिए। प्रक्रिया प्रबंधन आपके विशेष ऑपरेटिंग सिस्टम पर निर्भर करता है, और कई तकनीकें perlipc में हैं।

कई CPAN मॉड्यूल IPC::Open2 या IPC::Open3, IPC::Run, Parallel::Jobs, Parallel::ForkManager, POE, Proc::Background, और Win32::Process सहित, मदद करने में सक्षम हो सकता है। ऐसे कई अन्य मॉड्यूल हैं जिनका आप उपयोग कर सकते हैं, इसलिए उन विकल्पों को अन्य विकल्पों के लिए भी देखें।

आप एक यूनिक्स की तरह सिस्टम पर हैं, तो आप एक सिस्टम कॉल जहां आदेश के अंत पर एक & डाल के साथ भाग प्राप्त करने में सक्षम हो सकता है:

system("cmd &") 

तुम भी कांटा का उपयोग कर कोशिश कर सकते हैं , जैसा कि perlfunc में वर्णित है (हालांकि यह वही बात है जो कई मॉड्यूल आपके लिए करेंगे)।

STDIN, STDOUT, और STDERR

मुख्य प्रक्रिया और backgrounded एक ("बच्चे" प्रक्रिया) का हिस्सा ही STDIN, STDOUT और STDERR filehandles दोनों साझा कर रहे हैं। यदि दोनों एक बार में उन्हें एक्सेस करने का प्रयास करते हैं, तो अजीब चीजें हो सकती हैं। आप बच्चे के लिए इन्हें बंद या फिर से खोलना चाह सकते हैं। आप पाइप खोलने के साथ इसे प्राप्त कर सकते हैं (perlfunc में खुले देखें) लेकिन कुछ प्रणालियों पर इसका मतलब है कि बाल प्रक्रिया माता-पिता से बाहर नहीं जा सकती है। सिग्नल आपको सिगचल सिग्नल, और संभवतः सिगिप भी पकड़ना होगा। पृष्ठभूमि प्रक्रिया समाप्त होने पर SIGCHLD भेजा जाता है। SIGPIPE भेजा जाता है जब आप किसी फ़ाइलहेडल को लिखते हैं जिसकी बाल प्रक्रिया बंद हो जाती है (एक अप्रचलित सिगिप आपके प्रोग्राम को चुपचाप मर सकता है)। यह सिस्टम के साथ कोई मुद्दा नहीं है ("cmd &")।

Zombies

आप बच्चे प्रक्रिया "काटते" जब यह खत्म तैयार किया जाना है।

$SIG{CHLD} = sub { wait }; 

$SIG{CHLD} = 'IGNORE'; 

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

unless ($pid = fork) { 
    unless (fork) { 
     exec "what you really wanna do"; 
     die "exec failed!"; 
    } 
    exit 0; 
} 
waitpid($pid, 0); 

ऐसा करने के लिए कोड के अन्य उदाहरणों के लिए perlipc में सिग्नल देखें। लाश सिस्टम के साथ कोई समस्या नहीं है ("प्रोग &")।

0

यह पर्ल के लिए पूरी तरह से एक स्पष्टीकरण नहीं है। एक ही समस्या सी और अन्य भाषाओं के तहत है।

सबसे पहले समझने की क्या प्रणाली आदेश करता है:

  • माता पिता प्रक्रिया काँटेदार बच्चे की प्रक्रिया के लिए प्रतीक्षा कर रहा है खत्म करने के लिए

    1. फोर्क्स
    2. बच्चे प्रक्रिया कॉल कार्यकारी तहत

    इससे कोई फर्क नहीं पड़ता कि आप एकाधिक तर्क या एक तर्क पारित करते हैं। अंतर, कई तर्कों के साथ, आदेश सीधे निष्पादित किया जाता है।एक तर्क के साथ, कमांड खोल से लपेटा जाता है, और अंत में के रूप में मार डाला: जब आप some_command par1 par2 & के रूप में एक आदेश पारित

    /bin/sh -c your_command_with_redirections_and_ambersand 
    

    , तो पर्ल दुभाषिया और कमांड के बीच है या bash प्रक्रिया एक रैपर के रूप में उपयोग की जाती है, और यह कुछ_command परिष्करण की प्रतीक्षा कर रही है। आपकी स्क्रिप्ट शैल दुभाषिया की प्रतीक्षा कर रही है, और कोई अतिरिक्त प्रतीक्षापिड आवश्यक है, क्योंकि पर्ल के फ़ंक्शन सिस्टम यह आपके लिए करता है।

    आप अपनी स्क्रिप्ट में सीधे इस तंत्र को लागू करना चाहते हैं, आपको:

    1. उपयोग कांटा कार्य करते हैं। उदाहरण देखें: http://users.telenet.be/bartl/classicperl/fork/all.html
    2. बच्चे की स्थिति के तहत (if), exec फ़ंक्शन का उपयोग करें। आपका उपयोगकर्ता सिस्टम के समान है, मैनुअल देखें। नोटिस, exec निष्पादित आदेश द्वारा बाल प्रक्रिया प्रोग्राम/सामग्री/डेटा कवर का कारण बनता है।
    3. मूल स्थिति के तहत (यदि, गैर-शून्य के साथ कांटा निकलता है), तो आप फोर्क फ़ंक्शन द्वारा लौटाई गई पिड का उपयोग करके प्रतीक्षापिक का उपयोग करते हैं।

    यही कारण है कि आप पृष्ठभूमि में प्रक्रिया को चला सकते हैं। मुझे उम्मीद है कि यह आसान है।

    सबसे सरल उदाहरण:

    if (my $pid = fork) { #exits 0 = false for child process, at this point is brain split 
        # parent ($pid is process id of child) 
        # Do something what you want, asynchronously with executed command 
        waitpid($pid); # Wait until child ends 
        # If you don't want to, don't wait. Your process ends, and then the child process will be relinked 
        # from your script to INIT process, and finally INIT will assume the child finishing. 
        # Alternatively, you can handle the SIGCHLD signal in your script 
    } 
    else { 
        # Child 
        exec('some_command arg1 arg2'); #or exec('some_command','arg1','arg2'); 
        #exit is not needed, because exec completely overwrites the process content 
    } 
    
  • +0

    के बजाय बहुत अच्छे सुधारों के लिए पीटर धन्यवाद:) – Znik

    संबंधित मुद्दे

     संबंधित मुद्दे