Bash:最后(尝试,除外)例外

发布于 2024-09-28 12:51:53 字数 1466 浏览 6 评论 0原文

我想在 bash 脚本末尾执行一些命令,即使用户按 CTRL+C 取消其执行。

我知道我可以从另一种编程语言(例如 Python)内部运行 bash 脚本,这样我就可以使用“finally”(try-finally)块来执行一些代码。

但知道 StackOverflow 是一个中心为了交换精彩的想法,我问是否有一种方法可以在我的 bash 脚本中做我想做的事情。

那么,想法?

编辑:

我想要的是杀死我的bash中打开的每个进程,即selenium和Xvfb进程。

我尝试将其写入代码中:

 trap "selenium_pids=$(ps ux | awk '/selenium/ && !/awk/ {print $2}');for pid in $selenium_pids; do kill -9 $pid;done; xvfb_pids=$(ps ux | awk '/Xvfb/ && !/awk/ {print $2}'); for pid in $xvfb_pids; do kill -9 $pid; done" EXIT

但这迫使我在脚本内部每次运行子进程时多次按“CTRL+C”,例如:

Testing nsi.bd.helpcenter ...^C:  --  Total time: 0min 0seg
Testing nsi.bibliography ...^C:  --  Total time: 0min 0seg
Testing nsi.digitallibrary ...^C:  --  Total time: 0min 0seg
Testing nsi.digitallibraryinstaller ...^C:  --  Total time: 0min 1seg
Testing nsi.digitallibraryskins ...^C:  --  Total time: 0min 0seg
....#continues

将陷阱行的最后一个从 EXIT 更改为 SIGINT ,如下所示:

trap "selenium_pids=$(ps ux | awk '/selenium/ && !/awk/ {print $2}');for pid in $selenium_pids; do kill -9 $pid;done; xvfb_pids=$(ps ux | awk '/Xvfb/ && !/awk/ {print $2}'); for pid in $xvfb_pids; do kill -9 $pid; done" SIGINT

做同样的事情。

现在按第一个 CTRL+C 退出怎么办?

因为我尝试在字符串的末尾添加“exit 1”,例如 trap "... ;exit 1"

它可以在第一个 CTRL+C 上退出,但没有杀死我想要的进程。

有想法吗?

I want to execute some commands on the end of the bash script, even if the user press CTRL+C to cancel its execution.

I know I can run the bash script from inside another programming language (for example, Python), so that I can use the 'finally' (try-finally) block to execute some code.

But knowing that StackOverflow is a center for exchanging fabulous ideas, I'm asking if is there a way to do what I want from inside my bash script.

So, ideas?

EDIT:

What I want is kill every proccess opened within my bash, i.e., selenium and Xvfb proccesses.

I tried writing this to the code:

 trap "selenium_pids=$(ps ux | awk '/selenium/ && !/awk/ {print $2}');for pid in $selenium_pids; do kill -9 $pid;done; xvfb_pids=$(ps ux | awk '/Xvfb/ && !/awk/ {print $2}'); for pid in $xvfb_pids; do kill -9 $pid; done" EXIT

But this oblige me to press "CTRL+C" many times, on each run of subprocess from inside my script, something like:

Testing nsi.bd.helpcenter ...^C:  --  Total time: 0min 0seg
Testing nsi.bibliography ...^C:  --  Total time: 0min 0seg
Testing nsi.digitallibrary ...^C:  --  Total time: 0min 0seg
Testing nsi.digitallibraryinstaller ...^C:  --  Total time: 0min 1seg
Testing nsi.digitallibraryskins ...^C:  --  Total time: 0min 0seg
....#continues

Changing the final of the trap line from EXIT to SIGINT , like this:

trap "selenium_pids=$(ps ux | awk '/selenium/ && !/awk/ {print $2}');for pid in $selenium_pids; do kill -9 $pid;done; xvfb_pids=$(ps ux | awk '/Xvfb/ && !/awk/ {print $2}'); for pid in $xvfb_pids; do kill -9 $pid; done" SIGINT

Makes the same thing.

What now to exit on the first CTRL+C?

Because I tried to add a "exit 1" to the final of the string , like
trap "... ;exit 1"

It worked to exit on the first CTRL+C, but didn't killed the processes I wanted.

Ideas?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

太阳哥哥 2024-10-05 12:51:53

通过这段代码得到了我想要的:

finalize_xvfb_and_selenium() {
    selenium_pids=$(ps ux | awk '/selenium/ && !/awk/ {print $2}')
    for pid in $selenium_pids; do 
        kill -9 $pid
    done 
    xvfb_pids=$(ps ux | awk '/Xvfb/ && !/awk/ {print $2}') 
    for pid in $xvfb_pids; do 
        kill -9 $pid
    done
}

finalize_xvfb_and_selenium_and_exit() {
    finalize_xvfb_and_selenium
    echo -e "\n\nXvfb and seleniumrc finalized. Exiting ..."
    exit 13
}

#trap (CTRL+C) signal, to finalize proccess running before exit
trap finalize_xvfb_and_selenium_and_exit SIGINT

我知道有比到处使用 kill -9 更好的资源。

Got what I wanted with this code:

finalize_xvfb_and_selenium() {
    selenium_pids=$(ps ux | awk '/selenium/ && !/awk/ {print $2}')
    for pid in $selenium_pids; do 
        kill -9 $pid
    done 
    xvfb_pids=$(ps ux | awk '/Xvfb/ && !/awk/ {print $2}') 
    for pid in $xvfb_pids; do 
        kill -9 $pid
    done
}

finalize_xvfb_and_selenium_and_exit() {
    finalize_xvfb_and_selenium
    echo -e "\n\nXvfb and seleniumrc finalized. Exiting ..."
    exit 13
}

#trap (CTRL+C) signal, to finalize proccess running before exit
trap finalize_xvfb_and_selenium_and_exit SIGINT

I'm aware that there are better resources than using kill -9 everywhere.

﹏雨一样淡蓝的深情 2024-10-05 12:51:53

你想要捕获信号。

当用户在终端按下 control-c 时,操作系统向当前进程发出 SIGINT。该信号可以被捕获并处理。如何做到这一点是一个与 shell 相关的问题,您应该检查 shell 手册页。

请注意,某些信号无法被捕获。值得注意的是 SIGKILL,它是 kill -9 发送的。


根据编辑:bash 可以返回您启动的程序的进程 ID。您可以随时捕获所有这些内容,这样您就不必解析 ps 的输出。您还可以考虑向您的孩子发送一些其他信号(可能是 SIGUSR1),并已在该信号上设置陷阱,以便他们递归地杀死他们的孩子。

综上所述,您已经进入了深贝壳魔法领域。有一些书可能会有所帮助,但我不知道书名。

You want to trap signals.

When the user hits control-c at the terminal the OS issues a SIGINT to the current process. This signal can be trapped and handles. How you do that is a shell dependent issue and you should check your shells man page.

Note that some signals can not be trapped. Notably SIGKILL which is what kill -9 sends.


In light of the edit: bash can return the process ID of programs that you start. It would be possible to capture all them as you go so that you don't have to parse the output of ps. You might also consider sending you children some other signal (maybe SIGUSR1) having already set up a trap on that so that they will recursively kill their children.

All that said, your getting into deep shell magic territory. There are some books around which might help, but I don't know the titles off the top of my head.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文