2015-04-24 90 views
1

我有一個Jenkins作業,作爲參數化構建觸發。它接受一個可選的String參數(HOSTNAMES),它可以是逗號分隔的主機名列表。用於爲PERL腳本構建CLI參數的Shell腳本

我需要將此逗號分隔的主機名列表作爲命令行參數傳遞給PERL腳本(在Execute shell構建步驟中)。

這裏是我處理輸入參數和構造執行shell生成步驟中的命令行參數:

cmd_options='' 
echo hostnames is $HOSTNAMES 
if [ "$HOSTNAMES" != "" ] 
    then 
    cmd_options+=" --hostnames \"$HOSTNAMES\"" 
fi 
perl myscript.pl $cmd_options 

在構建的控制檯輸出雖然,我看到正在傳遞的參數不正確。這裏是控制檯輸出:

+ cmd_options= 
+ echo hostnames is host1, host2 
hostnames is host1, host2 
+ '[' 'host1, host2' '!=' '' ']' 
+ cmd_options+=' --hostnames "host1, host2"' 
+ perl myscript.pl --hostnames '"host1,' 'host2"' 

我想myscript.pl被稱爲是這樣的:

perl myscript.pl --hostnames "host1, host2" 

我曾嘗試使用單引號和雙引號操作$cmd_options的各種方式,但並不成功,到目前爲止在正確的情況下。任何指向我出錯的地方?

+1

爲什麼不重寫Perl腳本呢? – reinierpost

+0

我可以做到這一點。但是我更多地提出了這個問題,試圖理解shell腳本的更多細節以及我錯過了什麼。 –

+0

你在用什麼外殼? –

回答

2

當您構建命令時,延遲插值並使用eval來執行它。

HOSTNAMES='host1, host2' 

cmd_options='' 
if [ "$HOSTNAMES" != "" ]; then 
    cmd_options+='--hostnames "$HOSTNAMES"' 
fi 

eval "prog $cmd_options" 

更好的解決方案是使用陣列。

HOSTNAMES='host1, host2' 

cmd_options=() 
if [ "$HOSTNAMES" != "" ]; then 
    cmd_options+=(--hostnames "$HOSTNAMES") 
fi 

prog "${cmd_options[@]}" 

如果prog是下面的程序:

#!/usr/bin/perl 
use feature qw(say); 
say [email protected]; say for @ARGV 

兩個片段輸出如下:

2 
--hostnames 
host1, host2 
+0

我強烈建議不要使用'eval '這裏,至少不是很確定'HOSTNAMES'的價值是否安全 – chepner

+0

@chepner,你錯了,'HOSTNAMES'的內容永遠不會傳遞給'eval',所以沒什麼可檢查的。 – ikegami

+0

啊,錯過了那個。$ HOSTNAMES'這個字符串被傳遞給'eval',它進行參數擴展。 – chepner

0

樣子你會無法嵌入列表裏面$cmd_options
因爲它阻止你使用引號的標誌正確 -
「逃逸」的報價痕用反斜槓(\"
轉換他們到一個正規的"字符 - 不是一個分隔符,因此,
他們只是連接到$HOSTNAMES列表的第一個和最後一個項目。

建議你下降這行:

cmd_options+=" --hostnames \"$HOSTNAMES\"" 

,相反,使用以下兩行,根據需要
(假設你仍然需要$cmd_options傳遞其他參數)

perl myscript.pl $cmd_options --hostnames "$HOSTNAMES" 
perl myscript.pl $cmd_options 

包裝在if聲明中,它應該看起來像這樣:

if [ "$HOSTNAMES" != "" ] 
then 
    perl myscript.pl $cmd_options --hostnames "$HOSTNAMES" 
else 
    perl myscript.pl $cmd_options 
fi 

另一種選擇是,以確保有沒有空格$HOSTNAMES列表 -
它將允許通過列表作爲一個參數和報價的標誌將不再需要了。

+0

我認爲他們仍然需要包含$ cmd_options以防其他選項。所以在第一種情況下可能類似於'perl myscript.pl $ cmd_options --hostnames「$ HOSTNAMES」',在第二種情況下也是如此,但沒有--hostnames選項。 – sockmonk

+0

@Gonen你能解釋一下爲什麼'--hostnames \「$ HOSTNAMES \」'不會簡單地導致'--hostnames「host1,host2」'與'$ cmd_options'連接在一起? –

+0

@sockmonk,謝謝 - 已經用您的評論更新了我的示例。 – Gonen

0

假設你不需要腳本的位置參數更多,你可以自己設置它們。 (這將在任何POSIX外殼中工作,其中陣列不可用。)

# Save any positional parameters first, if necessary; 
# we're going to overwrite them. 
first_arg=$1 
second_arg=$2 
# etc. 
set -- --hostnames "$HOSTNAMES" 
perl myscript.pl "[email protected]"