m4x*_*4xx 4 linux bash command-line shell-script bash-scripting
我正在尝试编写一个脚本,其中如果有人按下CTRL+ C(键盘中断),那么它不应该退出整个脚本,而只是退出当前的执行函数。
谁能建议我在这里可以使用什么逻辑?这是相同的一些示例代码
#!/bin/bash
func1()
{
wget https://example.com/test1.txt
cat text1.txt |awk '{print $3}'|tr -d '.' > temp1.txt
}
func2()
{
cat temp1.txt|<stdin-to-some-tool> > temp2.txt
}
func3()
{
<some-tool> temp2.txt > temp3.txt
}
Run Code Online (Sandbox Code Playgroud)
同样,如果我们在此之前停止该函数,其他函数仍应执行。
Kam*_*ski 16
当您点击Ctrl+时c,终端的线路规则会发送SIGINT到前台进程组中的进程。
当禁用作业控制时,Bash 会在与进程bash本身相同的进程组中运行所有内容。当 Bash 解释脚本时,默认情况下禁用作业控制。这意味着如果脚本在前台运行,则解释该脚本的 shell 以及该脚本调用的所有内容将属于前台进程组1,并且将SIGINT在Ctrl+c上接收。
您可以通过 按需启用作业控制set -m。启用作业控制后,Bash 在单独的进程组中运行命令,并且Ctrl+c当前作为前台进程组的组。
这导致了解决问题的两种基本方法。
\ntraps该解决方案无需作业控制即可工作。当 Bash 解释脚本时,默认情况下禁用作业控制,因此不需要显式配置 shell。
\n一个进程可能会忽略SIGINT. 如果这样做,那么它的子级也会SIGINT忽略2。即使解释脚本的 shell 不忽略SIGINT,它也可能使其某些子进程忽略它3。
您希望主 shell 忽略SIGINT. 你希望它执行以下操作:
trap \'\' INT\nRun Code Online (Sandbox Code Playgroud)\n同时您希望您的功能不被忽略SIGINT。你希望他们这样做:
trap - INT\nRun Code Online (Sandbox Code Playgroud)\n要正确执行此操作,您需要使用子 shell。foo () { \xe2\x80\xa6 }用 定义并执行的函数foo作为主 shell 的一部分运行,因此trap \xe2\x80\xa6 INT函数内部将影响主 shell。这样的函数可以根据需要在子 shell 中运行(例如,作为(foo)或在管道中),然后它的陷阱不会影响主 shell。使用 定义的函数foo () ( \xe2\x80\xa6 )将始终在子 shell 中运行。对于您想要做的事情,最好以这种方式定义函数4。
概念证明:
\ntrap \'\' INT\nRun Code Online (Sandbox Code Playgroud)\nCtrl+c将中断sleep该函数(您不会看到foo returns),但不会中断主 shell。
请注意,您直接从脚本的主要部分(即不是从函数)运行的任何命令都将继承其设置为ignore SIGINT。要运行不忽略它的命令,您不一定需要函数,一个子 shell 就足够了。例子:
trap - INT\nRun Code Online (Sandbox Code Playgroud)\nCtrl同样,您可以在不受+影响的脚本中从易受+c影响的函数内部运行不受+影响的命令。这完全取决于您在哪个(子)shell 中调用什么。CtrlcCtrlctrap
(已删除。不再有效。我认为它曾经有效。正在调查中。)
\n1除非某些进程故意离开组。
\n2除非某些子进程故意选择不忽略。
\n3例如,在脚本中启动的异步进程ignoreSIGINT。这样,尽管它们位于前台进程组中,但它们不会对Ctrl+做出反应。c为了进行比较:在交互式 Bash 中(默认情况下启用作业控制)任何在后台启动的内容(即终止&)都不会对Ctrl+做出反应,因为它一开始c就没有出现。SIGINT它没有得到,SIGINT因为它位于一个单独的进程组中,而不是前台进程组。但是当你使用fg它时,它的组就变成了前台进程组。当在前台时,它可以对Ctrl+做出反应c。
4但是,如果您希望该函数在其他方面影响主 shell(例如修改主 shell 的变量),那么它一定不能在子 shell 中运行。这些要求可能会相互矛盾。
\n| 归档时间: |
|
| 查看次数: |
15709 次 |
| 最近记录: |