【问题标题】:Kill Bash Script from within a python exception从 python 异常中杀死 Bash 脚本
【发布时间】:2019-01-01 04:21:03
【问题描述】:

我有一个调用 Python 的 shell 脚本。

#! /bin/bash

shopt -s extglob
echo "====test===="
~/.conda/envs/my_env/bin/python <<'EOF'

import sys
import os


try:
    print("inside python")
    x = 2/0
except Exception as e:
    print("Exception: %s" % e)
    sys.exit(2)
print("at the end of python")
EOF
echo "end of script"

如果我执行这个,下面的行仍然会被打印出来。

"end of script"

我想在python脚本的异常块中退出shell,让脚本无法到达EOF

有没有办法在上面的except 块中创建和杀死subprocess,这会杀死整个shell 脚本?

我可以通过杀死整个 shell 脚本来生成一个虚拟子进程并在异常块内杀死它吗?

任何示例都会有所帮助。 提前致谢。

【问题讨论】:

  • 只保存你调用python那一行的返回值,在EOF之后检查
  • 或有非零返回码状态退出您的外壳 (set -e)。也不要做sys.exit(-1)。退出代码是肯定的。便携尊重范围0-255
  • @Jean-FrançoisFabre 我不想set -e 因为我希望一些错误静默失败并在脚本中继续,但特别是这个python异常会杀死整个脚本。谢谢,不会使用-1,编辑了帖子。
  • 这个问题不是重复的......
  • 问题是如何根据python脚本的功能退出脚本,正如提问者所重申的那样。

标签: python bash shell subprocess sh


【解决方案1】:

整个 EOF ... EOF 块在 Python 运行时中执行,因此退出它不会影响 bash 脚本。如果要停止进一步的 bash 脚本进度,则需要收集退出状态并在 Python 执行后检查它,即:

#!/bin/bash

~/.conda/envs/my_env/bin/python <<'EOF'
import sys

sys.exit(0x01)  # use any exit code from 0-0xFF range, comment out for a clean exit

print("End of the Python script that will not execute without commenting out the above.")
EOF

exit_status=$?  # store the exit status for later use

# now lets check the exit status and see if python returned a non-zero exit status
if [ $exit_status -ne 0 ]; then
    echo "Python exited with a non-zero exit status, abort!"
    exit $exit_status  # exit the bash script with the same status
fi
# continue as usual...
echo "All is good, end of script"

【讨论】:

    【解决方案2】:

    在 shell 脚本中,您有 2 个选项:

    • set -e:所有错误退出脚本
    • 检查 python 子命令返回码,如果非零则中止

    (也许这里有更多细节:Aborting a shell script if any command returns a non-zero value?

    现在,如果您不想更改 shell 脚本的处理方式,您可以获取 python 脚本的父进程并将其杀死:

    except Exception as e:
        import os,signal,sys
        print("Exception: %s" % e)
        os.kill(os.getppid(),signal.SIGTERM)
        sys.exit(2)
    

    如果你在 Windows 上需要这个,这不起作用(os.kill 不存在),你必须调整它以调用 taskkill

    subprocess.call(["taskkill","/F","/PID",str(os.getppid())])
    

    现在我想说杀死父进程是不好的做法。除非你不控制这个父进程的代码,否则你应该尽量优雅地处理退出。

    【讨论】:

    • 谢谢! os.kill 不接受 2 个参数,另一个是 sig 吗?
    • 谢谢,这正是我想要的。更干净,更漂亮。像魅力一样工作。
    • 我不会称之为更清洁,但如果你有 300 个 shell 脚本,你可能不想全部修改它们,所以这是只在 python 脚本中更改的解决方案。这仅在外壳 BTW 直接调用 时才有效。
    【解决方案3】:

    杀死整个脚本的一种方法是保存 PID,然后在异常发生时使用 Python 的系统命令在 PID 上执行 kill 命令。如果我们导入 'os',它将类似于以下内容:

    # In a shell
    PID=$$
    ...
    // Some Python Exception happens
    os.system('kill -9' + $PID)
    

    【讨论】:

      猜你喜欢
      • 2017-03-31
      • 2016-01-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-05-02
      • 1970-01-01
      • 2015-12-22
      • 2015-10-05
      相关资源
      最近更新 更多