我有一個 bash 腳本,名稱test.sh
如下:
#!/bin/bash
while :
do
echo xxx
sleep 1
done
我不知道為什麼./test.sh & | ./test.sh
給我一個錯誤:-bash: syntax error near unexpected token |'
,而./test.sh | ./test.sh
和./test.sh | ./test.sh &
工作。
答案1
shell 根本不允許這樣做文法:
%start complete_command %% complete_command : list separator | list ; list : list separator_op and_or | and_or ; ... pipe_sequence : command | pipe_sequence '|' linebreak command ; ... separator_op : '&' | ';' ;
請注意如何&
或;
只能終止列表,並且列表只是complete_command的一部分,它不能是其他產生式的一部分。
這只是一個語法上的怪癖;正如{ foo & }
在語義上類似於foo &
(大括號與圓括號不同,僅用於對命令進行分組,它們本身不會創建子shell或任何類型的範圍),如果允許後者,您可以認為{ foo & } | bar
在語義上類似於foo & | bar
所以你的例子的解決方法就是:
{ ./test.sh & } | ./test.sh
如果您從互動式 shell 運行它,請&
注意不是創建一個後台工作,但只需非同步運行命令,因為管道的右側始終在子 shell 中運行,並且子 shell 中的命令在禁用作業控制的情況下運行。
這類似於:
(sleep 3600 &)
子 shell 中的非同步列表(以 終止的命令&
)運行時,它們的 stdin 被重定向/dev/null
,並且它們的SIGINT
和SIGQUIT
訊號被忽略。它們將繼續在後台運行,但您不能像處理常規作業那樣使用 、they 等fg
將它們帶到前台。disown
此外,當它們被停止或終止時,您也不會收到通知。
在腳本中,這絕對沒有區別,因為腳本是在停用作業控制的情況下執行的。
但是如果你想透過管道輸出背景工作到前台工作在一個互動的shell,我能想到的唯一可移植的解決方案是使用命名管道。
$ mkfifo fifo
$ command | filter1 > fifo & # this is the background job
$ < fifo sed 10q | filter2 # this is the foreground job