You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 06:25:47