Linux下如何将Python子进程通过管道传递给batch命令?
Python脚本通过batch队列执行后任务未清除的问题排查
我尝试将Python脚本通过管道传给Linux的batch命令实现任务队列,用bash启动嵌套子进程。Python脚本能成功生成文本文件,进程返回码为0,但atq检查时任务始终留在队列里,stderr输出任务编号但没有具体错误信息,也没收到batch本该发送的错误邮件。
调用子进程的代码
process = subprocess.Popen(["/bin/sh", "-c", f"python ./atqTest/hello.py --stuff 1980 | batch"], stdout=subprocess.PIPE, stderr=subprocess.PIPE) out, err = process.communicate() print(f'out: {out.decode()}') print(f'err: {err.decode()}') print(process.returncode)
hello.py内容
import sys, argparse def parse_args(args): """Parses command line agruments.""" parser = argparse.ArgumentParser( description="""do stuff""", usage="""--stuff <random arg>\n""" ) parser.add_argument( "--stuff", required=True, help="""put something in""" ) return parser.parse_args(args) def main(): parser = parse_args(sys.argv[1:]) with open(f'/Documents/test/test.txt', 'w') as f: for item in parser.stuff: f.write(item + '\n') if __name__ == "__main__": main()
执行输出
out: err: job 94 at Thu Aug 17 10:01:23 2023 0
atq检查结果
94 Thu Aug 17 10:01:00 2023
尝试过的其他调用方式
process = subprocess.Popen(f"python ./atqTest/hello.py --stuff 1980 | batch", stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
问题原因
batch的使用逻辑错误:当前管道是把python hello.py的执行输出传给batch,但batch需要的是待执行的命令字符串,不是命令的运行结果。这导致batch拿到无效内容,无法正确执行任务,所以任务一直滞留在队列。- 文件路径错误:
/Documents/test/test.txt是根目录下的路径,普通用户无权限写入且该目录大概率不存在,batch后台执行脚本时会报错,但你无法直接看到错误信息。
解决方法
1. 修正batch调用方式
要让batch执行Python脚本,需把命令本身传给它,而非命令输出:
- 方式一:用
echo传递命令
process = subprocess.Popen( ["/bin/sh", "-c", "echo 'python ./atqTest/hello.py --stuff 1980' | batch"], stdout=subprocess.PIPE, stderr=subprocess.PIPE )
- 方式二:用临时文件传递命令(适合复杂场景)
import tempfile import os with tempfile.NamedTemporaryFile(mode='w', delete=False) as f: f.write("python ./atqTest/hello.py --stuff 1980\n") process = subprocess.Popen( ["batch", "-f", f.name], stdout=subprocess.PIPE, stderr=subprocess.PIPE ) os.unlink(f.name) # 清理临时文件
2. 修正文件路径
将hello.py中的路径改为正确的用户目录路径:
import os # 自动获取用户Documents目录 doc_path = os.path.expanduser('~/Documents/test/test.txt') with open(doc_path, 'w') as f: for item in parser.stuff: f.write(item + '\n')
3. 查看错误详情
- 查看
atd日志:sudo cat /var/log/atd.log,里面会记录batch任务的执行错误。 - 查看本地邮件:
batch会把执行结果发送到当前用户的本地邮箱,输入mail命令进入交互界面查看邮件内容。
内容的提问来源于stack exchange,提问作者MKF
相关产品推荐
相关产品推荐

