2016-03-03 76 views
2

我有一種情況,我需要檢測是否存在一個特定的perl可執行文件/usr/goofy/bin/perl,如果有,請使用它來運行Perl腳本,否則使用/usr/bin/perl有條件的Perl Shebang?

我一直在努力與這個小POC腳本,叫perlshebang.pl

#!/bin/sh -e 
perls="/usr/goofy/bin/perl /usr/bin/perl" 
for pl_exec in $perls 
do 
    if [ -x $pl_exec ]; then 
     exec "$pl_exec -w -S \"$0\" ${1+\"[email protected]\"}" 
    fi 
done 

print "[$^X] Whoop!\n"; 

當我的系統上運行此不具有/usr/goofy/bin/perl我收到此錯誤信息:

./perlshebang.pl: 6: exec: /usr/bin/perl -w -S "./perlshebang.pl" : not found 

而且當我運行它有一個系統確實有/usr/goofy/bin/perl我得到一個similuar錯誤信息:

./perlshebang.pl: line 6: /usr/goofy/bin/perl -w -S "./perlshebang.pl" : No such file or directory 

我想我很接近,但無法弄清楚爲什麼我會收到這些錯誤消息。

謝謝!

+3

正確的方法來處理這將是依靠路徑中的標準優先規則。首先搜索'PATH'開頭的內容。 –

+0

是的,這將是很好的。但是我無法控制腳本將要運行的所有系統上的PATH。 –

+3

這更糟。如果這是你正在發佈的東西,並且需要一定的Perl版本或風格,那麼你就要求它。 –

回答

1

我的一位同事提出了這個問題。我不確定我完全理解它,但它似乎工作正常:

#!/bin/sh 
#! -*-perl-*- 
eval ' if test -x /usr/goofy/bin/perl ; then 
    exec /usr/goofy/bin/perl -x -S $0 ${1+"[email protected]"}; 
elif test -x /usr/bin/perl ; then 
    exec /usr/bin/perl -x -S $0 ${1+"[email protected]"}; 
fi ' 
if $running_under_some_shell; 


use strict; 
use warnings; 
print "hello world\n"; # if $foo; 
printf("running %s v(%vd)\n", $^X, $^V); 

__END__ 

unpod like docs. 
See http://perldoc.perl.org/perlrun.html 
+1

,因爲您使用的是perl的'-x'命令行開關,您可以將第二個'#!'行下移到'use strict'之前不需要用'if $ running_under_some_shell'這一行來「隱藏」你的shell腳本。 – tjd

1

您可以運行一個運行/usr/bin/perl的Perl腳本。在腳本中使用帶有'goofy perl'的shebang行來運行。然後運行以下包裝器,然後運行腳本的正常調用(其名稱和參數)。

#!/usr/bin/perl 

exec "@ARGV"; 
exec "/usr/bin/perl @ARGV"; 

print STDERR "Couldn't execute either.\n"; 

讓我們把上述pick_perl.pl,和你的腳本script.pl。運行它作爲

 
pick_perl.pl script.pl args-for-script 

exec與一個它執行,即完全取代了正在運行的程序。它加載新程序。這樣你的腳本就會運行自己的shebang。如果失敗exec安靜地返回(帶有false)並且下一個語句被執行,所以另一個Perl運行腳本(覆蓋shebang)。如果腳本的shebang失敗,則會發生這種情況,但如果第一個exec由於任何原因未能執行,則會發生這種情況。

如果您希望/需要運行支票,請將exec放在完整的if區塊中。如果-e不能保證足夠,還可以進一步詢問'goofy_perl'文件。

#!/usr/bin/perl 

$system_perl = "/usr/bin/perl"; 
$goofy_perl = "/usr/goofy/bin/perl"; 

# Your 'goofy_perl' script with its arguments 
@script_cmd = @ARGV; 

if (-x $goofy_perl) { exec "@script_cmd" } 

exec "$system_perl @script_cmd"; 

@script_cmd有你的腳本完整的命令行(其中有「goofy_perl」家當)。

+0

我似乎陷入了遞歸循環。 –

+0

@RedCricket我不知道這是否仍然是你感興趣的,但我意識到我可能沒有迴應 - 在第一版中,我不清楚如何運行這個簡短的包裝。現在應該清楚了,它必須工作。道歉,如果這個評論是過分的。 – zdim

2

這聽起來有點醜陋給我,如果你是發佈使用該破解

如果你沒有其他選擇軟件,那麼我建議你確保有總是一個/usr/goofy/bin/perl,並使用shebang line

#!/usr/goofy/bin/perl 

所有的腳本。

對於您要使用系統perl的這些系統,才使得/usr/goofy/bin/perl一個符號鏈接/usr/bin/perl

+0

我正在與這個,但我將不得不宣佈它爲我的老闆「解決方法」。 –

+0

@RedCricket:解決方法是有時在用戶目錄中保留自定義perl構建的策略。你的應用程序應該和'/ opt'一起運行。如果您的問題得到解答,請將其中一個答案標記爲 – Borodin

3

要回答你的問題,「爲什麼我會得到這些錯誤信息」,問題是你的exec行:

exec "/path/to/cmd arg arg" 
# This will attempt to execute a file named "cmd arg arg" 
# (with spaces in name) in directory /path/to/ 

對比度與

exec /path/to/cmd arg arg 
# This will attempt to execute a file named "cmd" in directory 
# /path/to/, with arguments "arg" and "arg" 

所以,這就是爲什麼外殼抱怨說,它不能鰭你的可執行文件。您沒有名爲perl -w -s "perlshebang.pl"的文件,既沒有在/usr/bin/下也沒有在/usr/goofy/bin/下。