Discord Python Bot执行Shell脚本:仅返回退出码,期望输出仅在终端的问题
如何让Discord Bot将Shell脚本的输出发送到频道?
你的问题核心在于:subprocess.call() 和默认参数的 subprocess.run() 不会捕获脚本的标准输出(stdout)和标准错误(stderr),这些输出会直接打印到运行Bot的本地终端,而不是被Bot获取并转发到Discord频道。
解决方案:捕获脚本输出并转发
我们需要修改subprocess.run()的参数,让它捕获脚本的输出,然后把这些内容发送到Discord。这里有两种常用的方式:
方法1:使用capture_output=True和text=True
capture_output=True会同时捕获stdout和stderr,text=True(等价于universal_newlines=True)会将字节流输出转换为字符串,方便直接发送。
修改后的完整代码:
@bot.command(pass_context=True) async def test(ctx, *, arg): await ctx.send(arg) # 执行脚本并捕获输出 process_result = subprocess.run( ["./test.sh", arg], capture_output=True, text=True ) # 发送脚本的标准输出(如果有内容) if process_result.stdout.strip(): await ctx.send(f"脚本输出:\n```\n{process_result.stdout}\n```") # 发送脚本的错误输出(如果有内容) if process_result.stderr.strip(): await ctx.send(f"脚本错误输出:\n```\n{process_result.stderr}\n```") # 发送返回码(可选) await ctx.send(f"脚本返回码: {process_result.returncode}")
方法2:显式指定stdout和stderr参数
如果你需要更精细的控制,也可以显式设置stdout=subprocess.PIPE和stderr=subprocess.PIPE,效果和上面一致:
process_result = subprocess.run( ["./test.sh", arg], stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True )
为什么原来的代码不行?
subprocess.call()只返回脚本的退出码,完全不捕获输出,所以你看到的0就是退出码。- 不带捕获参数的
subprocess.run()同样会把输出打印到本地终端,返回的CompletedProcess对象里虽然包含stdout和stderr,但默认是None,只有当你设置了捕获参数后才会填充这些值。
额外注意事项
- 确保你的
test.sh脚本有执行权限(可以用chmod +x test.sh设置)。 - 如果脚本输出内容过长(超过Discord单条消息2000字符的限制),你需要把内容分块后再发送,避免发送失败。
- 如果脚本需要从标准输入读取内容,你可能还需要设置
stdin=subprocess.PIPE并通过input参数传递数据。
内容的提问来源于stack exchange,提问作者Turtle
相关产品推荐
相关产品推荐

