在我的bash脚本中,我正在运行一个存储在$cmd
变量中的外部命令。 (它可能是任何东西,甚至是一些简单的bash oneliner。)
如果在运行脚本时按 ctrl + C ,我希望它能够终止当前正在运行的$cmd
,但它仍应继续运行主脚本。但是,我想在主脚本运行时保留使用 ctrl + C 终止主脚本的选项。
#!/bin/bash
cmd='read -p "Ooook?" something; echo $something; sleep 4 '
while true; do
echo "running cmd.."
eval "$cmd" # ctrl-C now should terminate the eval and print "done cmd"
echo "done cmd"
sleep 5 # ctrl-C now should terminate the main script
done
任何想法如何做一些不错的bash方式?
根据答案应用的更改:
#! /bin/bash
cmd='read -p "Ooook1?" something; read -p "Oook2?" ; echo $something; sleep 4 '
while true; do
echo "running cmd.."
trap "echo Interrupted" INT
eval "($cmd)" # ctrl-C now should terminate the eval and print "done cmd"
trap - INT
echo "done cmd"
sleep 5 # ctrl-C now should terminate the main script
done
现在,按下 ctrl + C 而“Ooook1?”只有在读取完成后,read才会中断eval。 (它会在“Oook2”之前中断)然而它会立即中断“睡眠4”。
在这两种情况下它都会做正确的事 - 它只会中断eval子shell,所以我们几乎就在那里 - 只是那种奇怪的读取行为......
答案 0 :(得分:4)
如果你能负担eval
部分在子shell中运行,你需要做的就是陷阱SIGINT。
#! /bin/bash
cmd='read -p "Ooook1?" something; read -p "Oook2?" ; echo $something; sleep 4 '
while true; do
echo "running cmd.."
trap "echo Interrupted" INT
eval "($cmd)" # ctrl-C now should terminate the eval and print "done cmd"
trap - INT
echo "done cmd"
sleep 5 # ctrl-C now should terminate the main script
done
不知道这是否符合您的特定需求。
$ ./t.sh
running cmd..
Ooook1?^CInterrupted
done cmd
^C
$ ./t.sh
running cmd..
Ooook1?qsdqs^CInterrupted
done cmd
^C
$ ./t.sh
running cmd..
Ooook1?qsd
Oook2?^CInterrupted
done cmd
^C
$
GNU bash, version 4.1.9(2)-release (x86_64-pc-linux-gnu)
答案 1 :(得分:0)
您可以通过检查上次退出状态echo $?
来确定sleep命令是否异常退出。非零状态可能表示Ctrl-C。
答案 2 :(得分:0)
不,read
不是外部命令,它是在与其他指令相同的进程中执行的内部内置bash
命令。因此,在Ctrl-C中,所有进程都将被终止。
P.S。 是。你可以在子shell中执行命令。像这样的东西
#!/bin/bash
cmd='trap - INT; echo $$; read -p "Ooook?" something; echo $something; sleep 4 '
echo $$
while true; do
echo "$cmd" > tmpfile
echo "running cmd.."
trap "" INT
bash tmpfile
rm tmpfile
trap - INT
echo "done cmd"
sleep 5 # ctrl-C now should terminate the main script
done