debugging 如何从只在终端外部失败的程序中捕获错误消息?

x4shl7ld  于 2023-01-26  发布在  其他
关注(0)|答案(2)|浏览(145)

在Linux服务器上,我这里有一个脚本,当我从终端启动它时,它可以正常工作,但当启动它并被另一个进程分离时,它会失败。
问题是,当脚本失败时,集成该脚本的另一个进程不提供对其错误消息的访问。当脚本失败时,有什么简单(理想情况下是通用的)方法可以查看这样一个脚本的输出?
让我们假设我没有简单的方法来修改调用这个脚本的进程的代码,失败发生在脚本运行的开始,所以没有足够的时间手动attach to it with strace to see its output
(The细节并不重要,重要的是:失败的脚本是Discourse的备份脚本,Discourse是一个广泛使用的开源论坛软件,Discourse和这个脚本都是用Ruby写的)

i7uq4tfw

i7uq4tfw1#

这个想法是用 Package 器代替原始脚本, Package 器调用原始脚本并将其stdin和stderr保存到文件中。

#!/bin/bash

exec /path/to/original/script "$@" 1> >(tee /tmp/out.log) 2> >(tee /tmp/err.log >&2)

1> >(tee /tmp/out.log)将stdout重定向到subshell中的tee /tmp/out.log输入。tee /tmp/out.log将其传递到stdout,但将副本保存到文件。
2> >(tee /tmp/err.log)将stderr重定向到subshell中的tee /tmp/err.log输入。tee /tmp/err.log >&2将其传递到stderr,但将副本保存到文件。
如果脚本被多次调用,您可能需要将stdout和stderr附加到文件。在这种情况下,请使用tee -a
问题是如何强制调用者执行 Package 器脚本而不是原始脚本。
如果调用方以在PATH中搜索脚本的方式调用脚本,则可以将 Package 脚本放在单独的目录中,并将修改后的PATH提供给调用方。例如,脚本名称为script。将 Package 放在/some/dir/script中,并将调用方作为

$ PATH="/some/dir:$PATH" caller

Package 中的/path/to/original/script必须是绝对值。
如果调用方从特定路径调用脚本,则可以将原始脚本重命名为original-script,并将 Package 器命名为script。在这种情况下, Package 器应调用/path/to/original/original-script
如果script的行为因其调用的名称不同而不同,则可能会出现另一个问题,在这种情况下可能需要exec -a ...

atmip9wb

atmip9wb2#

您可以使用bash脚本,**(1)执行“忙碌waiting”,直到看到目标进程,然后(2)**立即使用strace附加到目标进程,并将其输出打印到终端。

#!/bin/sh

# Adapt to a regex that matches only your target process' full command.
name_pattern="bin/ruby.*spawn_backup_restore.rb"

# Wait for a process to start, based on its name, and capture its PID.
# Inspiration and details: https://unix.stackexchange.com/a/410075
pid=
while [ -z "$pid" ] ; do
    pid="$(pgrep --full "$name_pattern" | head -n 1)"

    # Set delay for next check to 1ms to try capturing all output.
    # Remove completely if this is not enough to capture from the start.
    sleep 0.001
done

echo "target process has started, pid is $pid"

# Print all stdout and stderr output of the process we found.
# Source and explanations: https://unix.stackexchange.com/a/58601
strace -p "$pid" -s 9999 -e write

相关问题