我想要一个可以获取命令列表、逐一执行它们并显示输出的脚本。问题是某些命令将启动新的 shell,这应该会影响后续命令。我在名为 的文件中有一些示例输入commands
。
echo "current shell: $0"
ksh
echo "current shell: $0"
exit
echo "current shell: $0"
我有这个脚本,test3.sh
它使用命名管道来发送命令。
#! /usr/bin/env bash
# Create a pipe for processing commands
rm -f shell-pipe
mkfifo shell-pipe
# Set up a bash shell to process the commands sent to the pipe
(tail -f shell-pipe | bash) &
while IFS='' read -r command; do
echo ">>> sending command: $command"
echo $command > shell-pipe
sleep 1
done
# Close the pipe and delete it
fuser -TERM -k shell-pipe > /dev/null
rm shell-pipe
有用。
$ ./test3.sh < commands
>>> sending command: echo "current shell: $0"
current shell: bash
>>> sending command: ksh
>>> sending command: echo "current shell: $0"
current shell: ksh
>>> sending command: exit
>>> sending command: echo "current shell: $0"
current shell: bash
但我事先不知道命令需要多长时间才能完成,所以我需要某种方法来确定命令是否已完成。所以我为响应设置了一个单独的命名管道。
$ cat test4.sh
#! /usr/bin/env bash
# Create a pipe for processing commands
rm -f shell-pipe response-pipe
mkfifo shell-pipe response-pipe
# Set up a bash shell to process the commands sent to the pipe
(tail -f shell-pipe | bash > response-pipe) &
while IFS='' read -r command; do
echo ">>> sending command: $command"
echo $command > shell-pipe
echo "...waiting for response..."
echo "<<< reponse: " $(cat response-pipe)
done
# Close the pipe and delete it
fuser -TERM -k shell-pipe > /dev/null
rm shell-pipe response-pipe
不幸的是,这个挂起,最终我不得不使用 Ctrl-c。
$ ./test4.sh < commands
>>> sending command: echo "current shell: $0"
...waiting for response...
^C
我尝试过使用该exec
命令,但这没有帮助。我bash
在这个例子中使用了,但很乐意使用另一个 shell、Python 或 Haskell。
答案1
如果您将其运行为(或任何一次bash < file
处理一行输入的 shell ),那么这将起作用:read
$ cat file
echo "current shell: $0"
ksh
echo "current shell: $0"
exit
echo "current shell: $0"
$ bash < file
current shell: bash
current shell: ksh
current shell: bash
$ zsh < file
current shell: zsh
current shell: ksh
current shell: zsh
(不适用于dash
在开始解释它所读取的内容之前读取整个文件(至少 8KiB 块)(不进行 bash 或 ksh 所做的搜索),因此 ksh 在启动时没有什么可读取的) 。
请注意,如果任何调用的命令(不仅仅是 shell)读取其标准输入,它们也会从脚本中读取,例如
export VAR=before
echo "$0 $VAR"
ksh
echo "$0 $VAR"
read VAR
after
echo "$0 $VAR"
exit
echo "$0 $VAR"
你会得到:
bash before
ksh before
ksh after
bash before