كيف يمكنك التقاط stderr, المعياري, ورمز الخروج في كل مرة ، في بيرل?

StackOverflow https://stackoverflow.com/questions/109124

  •  01-07-2019
  •  | 
  •  

سؤال

هل من الممكن تشغيل عملية خارجية من Perl, التقاط stderr ، المعياري و عملية خروج الرمز ؟

يبدو لي أن تكون قادرة على القيام تركيبات من هذه ، على سبيل المثالاستخدام backticks للحصول على المعياري الدولي للبراءات::Open3 لالتقاط مخرجات النظام() للحصول على رموز الإنهاء.

كيف يمكنك التقاط stderr, المعياري, ورمز الخروج في كل مرة ؟

هل كانت مفيدة؟

المحلول

إذا كنت قراءة وثائق التصنيف::Open3 ، سترى ملاحظة أنه يجب الاتصال waitpid جني عملية طفل.بمجرد القيام بذلك ، وحالة ينبغي أن تكون متاحة في $?.خروج القيمة $? >> 8.انظر $? في perldoc perlvar.

نصائح أخرى

(التحديث:أنا تحديث API IO::CaptureOutput لجعل هذا أسهل.)

هناك عدة طرق للقيام بذلك.هنا خيار واحد ، باستخدام IO::CaptureOutput الوحدة النمطية:

use IO::CaptureOutput qw/capture_exec/;

my ($stdout, $stderr, $success, $exit_code) = capture_exec( @cmd );

هذا هو capture_exec() وظيفة ، ولكن IO::CaptureOutput أيضا أعم القبض() وظيفة التي يمكن استخدامها لالتقاط إما Perl أو الإنتاج أو الإخراج من البرامج الخارجية.حتى إن بعض Perl module يحدث أن استخدام بعض برامج خارجية, كنت لا تزال تحصل على الناتج.

كما يعني أنك تحتاج فقط إلى تذكر نهج واحد لالتقاط المعياري و STDERR (أو دمجها) بدلا من استخدام التصنيف الدولي للبراءات::Open3 الخارجية البرامج و وحدات أخرى من أجل التقاط بيرل الانتاج.

إذا كنت لا تريد محتويات STDERR, ثم التقاط() أمر من التصنيف::النظام::بسيطة وحدة تقريبا بالضبط ما كنت بعد:

   use IPC::System::Simple qw(capture system $EXITVAL);

   my $output = capture($cmd, @args);

   my $exit_value = $EXITVAL;

يمكنك استخدام التقاط() مع حجة واحدة الاحتجاج قذيفة ، أو حجج متعددة موثوق تجنب قذيفة.هناك أيضا capturex() الذي لا يدعو قذيفة ، حتى مع حجة واحدة.

على عكس بيرل المدمج في نظام backticks الأوامر ، IPC::النظام::بسيطة بإرجاع كامل 32 بت الخروج قيمة تحت ويندوز.كما يلقي مفصل استثناء إذا كان الأمر لا يمكن أن يكون بدأ يموت إشارة ، أو عائدات غير متوقعة خروج القيمة.وهذا يعني بالنسبة للعديد من البرامج بدلا من التحقق من الخروج قيم نفسك, يمكنك الاعتماد عليها التصنيف::النظام::بسيطة للقيام بهذا العمل الشاق بالنسبة لك:

 use IPC::System::Simple qw(system capture $EXIT_ANY);

 system( [0,1], "frobincate", @files);     # Must return exitval 0 or 1

 my @lines = capture($EXIT_ANY, "baznicate", @files);  # Any exitval is OK.

 foreach my $record (@lines) {
     system( [0, 32], "barnicate", $record);  # Must return exitval 0 or 32
 }

التصنيف::النظام::بسيطة نقية بيرل ، ليس له تبعيات و يعمل على كل Unix و أنظمة ويندوز.للأسف لا توفر طريقة التقاط STDERR, لذلك قد لا تكون مناسبة لجميع الاحتياجات الخاصة بك.

التصنيف::Run3 يوفر واجهة نظيفة وسهلة في إعادة السباكة الثلاثة المشتركة filehandles ، ولكن لسوء الحظ أنها لا تحقق لمعرفة ما إذا تم الأمر بنجاح, لذلك سوف تحتاج إلى فحص $?يدويا مما ليس في كل متعة.توفير واجهة عامة للتفتيش $?هو شيء في بلدي قائمة بالنسبة للتصنيف::النظام::بسيطة منذ تفتيش $?عبر منصة الأزياء ليست مهمة أتمنى على أي شخص.

وهناك وحدات أخرى في التصنيف:: مساحة الاسم التي يمكن أن توفر لك أيضا مع المساعدة.YMMV.

كل خير ،

بول

هناك ثلاث طرق أساسية تشغيل الأوامر الخارجية:

system $cmd;        # using system()
$output = `$cmd`;       # using backticks (``)
open (PIPE, "cmd |");   # using open()

مع system(), سواء STDOUT و STDERR سوف تذهب نفس مكان البرنامج النصي STDOUT و STDERR, ما لم system() الأمر الموجهات لهم.Backticks ، open() قراءة فقط STDOUT من القيادة.

يمكنك أيضا استدعاء شيء كما يلي مع فتح إلى إعادة توجيه كل من STDOUT و STDERR.

open(PIPE, "cmd 2>&1 |");

رمز الإرجاع هو دائما المخزنة في $? كما لوحظ من قبل @مايكل كارمان.

إذا كنت الحصول على معقدة حقا ، قد ترغب في محاولة نتوقع.مساء.ولكن هذا ربما مبالغة إذا كنت لا تحتاج إلى إدارة أيضا إرسال مدخلات العملية أيضا.

وجدت التصنيف:run3 أن تكون مفيدة جدا.يمكنك إعادة توجيه كل طفل الأنابيب الكرة أو متغير ؛ بسهولة جدا!و الخروج على القانون سيتم تخزينها في $?.

أدناه هو كيف لي أن أمسك stderr الذي عرفت أنه يكون عددا.Cmd إخراج المعلوماتية التحولات المعياري (الذي إيصاله إلى ملف في وسائط باستخدام >) و ذكرت كيف العديد من التحولات إلى STDERR.

use IPC::Run3

my $number;
my $run = run3("cmd arg1 arg2 >output_file",\undef, \undef, \$number);
die "Command failed: $!" unless ($run && $? == 0);
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top