[英]bash script concatenates input arguments with pipe xargs arguments
我正在嘗試執行我的腳本,但 $1 參數與最后一個管道的參數連接,導致以下結果
killProcess(){
ps aux |grep $1 | tr -s " " " " | awk "{printf \"%s \",\$2}" | tr " " "\n" | xargs -l1 echo $1
}
$killProcess node
node 18780
node 965856
node 18801
node 909028
node 19000
node 1407472
node 19028
node 583620
node 837
node 14804
node 841
node 14260
但我只想要pids列表,沒有節點參數能夠刪除它們,只有當我把它放在腳本下時才會發生,在命令行中它對我來說正常工作,因為我沒有將任何參數傳遞給腳本它不會被連接起來。
直接的問題是你不想要最后的$1
。 在這種情況下, $1
擴展為函數的第一個參數(在您的示例中為“node”),然后將其傳遞給xargs
並被視為它應該執行的命令的一部分。 也就是說,管道的最后一部分擴展為:
xargs -l1 echo node
...所以當xargs
接收“18780”作為輸入時,它會運行echo node 18780
,這當然會打印“node 18780”。
解決方案:刪除$1
,使命令只是xargs -l1 echo
,所以當 xargs 接收“18780”作為輸入時,它運行echo 18780
, echo 18780
打印“18780”。
這會解決它,但也有大量的簡化可以在這里完成。 管道的許多元素沒有做任何有用的事情,或者彼此交叉工作。
從管道中的最后一個命令xargs
。 它接收PID,每行一個,並每行打印一個。 它根本沒有做任何事情(無論如何我都可以看到),所以就不要再管了。 (當然,除非您真的想使用kill
而不是echo
—— 在這種情況下,請保持打開狀態。)
現在從最后看接下來的兩個命令:
awk "{printf \"%s \",\$2}" | tr " " "\n"`
在這里, awk
在每個 PID 后面打印一個空格,然后tr
將空格轉換為換行符。 為什么不讓awk
以換行符開頭打印每個? 為此,您甚至不需要printf
,您可以只使用print
因為它會自動添加換行符。 將腳本以單引號傳遞給awk
也更簡單,因此您不必轉義雙引號、美元符號和(可能)反斜杠。 所以這些都可以工作:
awk "{printf \"%s\\n\",\$2}"
awk '{printf "%s\n",$2}'
awk '{print $2}'
當然,我推薦最后一個。
現在,關於awk
之前的命令: tr -s " " " "
。 這將空格運行“擠壓”為單個空格,但這不是必需的,因為awk
將空格運行視為(單個)字段分隔符。 所以,再一次,把這個命令排除在外。
在這一點上,我們歸結為以下管道:
ps aux | grep $1 | awk '{print $2}'
這里還有兩件事我要推薦。 首先,您應該(幾乎)始終在 shell 變量、參數等引用(如$1
周圍使用雙引號。 因此,請改用grep "$1"
。
但是不要那樣做,因為awk
完全有能力進行搜索; 不需要grep
和awk
。 事實上, awk
可以更精確,只搜索特定字段而不是整行。 缺點是,它做起來有點復雜,但知道如何讓awk
做更復雜的事情是有用的。 讓awk
與 shell 變量或參數一起工作的最好方法是使用它的-v
選項來創建一個具有相同值的 awk 變量,然后使用它。 然后,您可以使用~
來檢查與變量的正則表達式匹配。 像這樣的東西:
awk -v proc="$1" '$11 ~ proc {print $2}'
注意:我假設您想在可執行文件名稱中搜索$1
,這是您系統上ps aux
的第 11 個字段。 僅搜索該字段將使其不匹配例如用戶名(殺死用戶的所有進程,因為他們的名稱包含一些程序名稱是不禮貌的)。 您實際上可能想要更具體,以便例如嘗試殺死node
也不會意外殺死nodemon
; 這將是使用更具體的搜索模式的問題。
所以,這是最終的結果:
killProcess(){
ps aux | awk -v proc="$1" '$11 ~ proc {print $2}'
}
要真正xargs -l1 kill
進程,請在最后添加xargs -l1 kill
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.