[英]Why shouldn't I use shell tools in Perl code?

It is generally advised not to use additional linux tools in a Perl code; e.g if someone intends to print the last line of a text file he can:


$last_line = `tail -1 $file` ;

or otherwise, open the file and read it line by line


 while(<INFO>) {
   $last_line = $_ if eof;

What are the pitfalls of using the previous and why should I avoid using shell tools in my code?



6 个解决方案


  • Efficiency - you don't have to spawn a new process
  • 效率 - 您不必生成新流程

  • Portability - you don't have to worry about an executable not existing, accepting different switches, or having different output
  • 可移植性 - 您不必擔心可執行文件不存在,接受不同的交換機或具有不同的輸出

  • Ease of use - you don't have to parse the output, the results are already in a usable form
  • 易於使用 - 您不必解析輸出,結果已經是可用的形式

  • Error handling - you have finer-grained control over errors and what to do about them in Perl.
  • 錯誤處理 - 您可以更好地控制錯誤以及在Perl中如何處理錯誤。


It's better to keep all the action in Perl because it's faster and because it's more secure. It's faster because you're not spawning a new process, and it's more secure because you don't have to worry about shell meta character trickery.


For example, in your first case if $file contained "afilename ; rm -rf ~" you would be a very unhappy camper.

例如,在第一種情況下,如果$ file包含“afilename; rm -rf~”,那么你將是一個非常不開心的露營者。

P.S. The best all-Perlway to do the tail is to use File::ReadBackwards

附:做尾巴的最好的全部Perlway是使用File :: ReadBackwards


One of the primary reasons (besides portability) for not executing shell commands is that it introduces overhead by spawning another process. That's why much of the same functionality is available via CPAN in Perl modules.



One reason is that your Perl code might be running in an environment where there is no shell tool called 'tail'.


It's a personal call depending on the project:


  • Is it going to be always used in shell environments with tail?
  • 是否總是在帶有尾部的shell環境中使用?

  • Do you care about only using pure Perl code?
  • 你只關心使用純Perl代碼嗎?


Using tail? Fine. But that's really a special case, since it's so easy to use and since it is so trivial.


The problem in general is not really efficiency or portability, that is largely irrelevant; the issue is ease of use. To run an external utility, you have to find out what arguments it accepts, write code to transform your program's data structures to that format, quote them properly, build the command line, and run the application. Then, you might have to feed it data and read data from it (involving complexity like an event loop, worrying about deadlocking, etc.), and finally interpret the return value. (UNIX processes consider "0" true and anything else false, but Perl assumes the opposite. foo() and die is hard to read.) This is a lot of work to do, and that's why people avoid it. It's much easier to create an instance of a class and call methods on it to get the data you need.

一般來說問題不是效率或可移植性,這在很大程度上是無關緊要的;問題是易用性。要運行外部實用程序,您必須找出它接受的參數,編寫代碼以將程序的數據結構轉換為該格式,正確引用它們,構建命令行並運行應用程序。然后,您可能必須提供數據並從中讀取數據(涉及事件循環等復雜性,擔心死鎖等),最后解釋返回值。 (UNIX進程認為“0”為真,其他任何都是假的,但Perl假設相反.foo()和die很難讀。)這是很多工作要做,這就是人們避免它的原因。創建類的實例並在其上調用方法以獲取所需的數據要容易得多。

(You can abstract away processes this way; see Crypt::GpgME for example. It handles the complexity associated with invoking gpg, which would normally involve creating multiple filehandles other than STDOUT, STDIN, and STDERR, among other things.)

(您可以通過這種方式抽象出過程;例如,請參閱Crypt :: GpgME。它處理與調用gpg相關的復雜性,這通常涉及創建除STDOUT,STDIN和STDERR之外的多個文件句柄。)


The main reason I see for doing it all in Perl would be for robustness. Your use of tail will fail if the filename has shell metacharacters or spaces or doesn't exist or isn't accessible. From Perl, characters in the filename aren't an issue, and you can distinguish between errors in accessing the file. Sometimes being robust is more important than speedy coding and sometimes it's not.




粤ICP备14056181号  © 2014-2021 ITdaan.com