从python异常中杀死Bash脚本

时间:2018-07-24 13:52:08

标签: python bash shell subprocess sh

我有一个在其中调用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脚本的异常块中退出外壳,并让脚本不到达EOF

是否有一种方法可以在上面的subprocess块中创建并杀死except,从而杀死整个shell脚本?

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

任何例子都会有帮助。 预先感谢。

3 个答案:

答案 0 :(得分:3)

整个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"

答案 1 :(得分:1)

在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())])

现在我要说杀死父进程是一种不好的做法。除非您不控制此父进程的代码,否则应尝试优雅地处理退出。

答案 2 :(得分:0)

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

initializeForm() {
    this.formGroupItemSelection = this.fb.group({
      refNumber : new FormControl(true),
      partNumber: new FormControl(false),
      itemName: new FormControl(false),
      manufacturerName: '',
      refNumberSelected:[
        null,
        Validators.compose([Validators.required, matchValuesRefNumber(this.listOfItems)])
      ],
      partNumberSelected:[
        null,
        Validators.compose([Validators.required, matchValuesPartNumber(this.listOfItems)])
      ],
      itemNameSelected: [
        null,
        Validators.compose([Validators.required, matchValuesItemName(this.listOfItems)])
      ],
      manufacturerNameSelected:[
        null,
        Validators.compose([Validators.required, matchValuesManufacturerName(this.listOfItems)])
      ]
    })

//This will set the radio button checked no need to add checked attribute you can set cheked dynamically
 this.formGroupItemSelection.get('refNumber ').setValue(true);
this.formGroupItemSelection.get('partNumber').setValue(true);
this.formGroupItemSelection.get('itemName').setValue(true)
  }