运行的但被修改的bash脚本是否可以查看原始内容?

3
假设我在后台运行一个bash脚本run.sh,然后我修改了run.sh。有没有办法查看run.sh脚本的原始内容?
例如:
echo "echo a1; sleep 120; echo a2" > run.sh; bash run.sh& 
aPid=$!
echo "echo bbbbbb" > run.sh

我期望有一个类似 cat {魔法文件/路径} 这样的命令,它会输出:
echo a1; sleep 120; echo a2

我正在浏览/proc/$aPid,但找不到任何内容。
2个回答

2

首先确保您的ulimit设置允许核心文件。请尝试:

ulimit -c unlimited

接下来,运行你的脚本。

./run.sh

在您的脚本运行时,修改或删除run.sh脚本文件。

执行ps ax查找第一个run.sh脚本的进程ID(PID)。您应该会看到类似以下内容:

19365 pts/5    S+     0:00 /bin/bash ./run.sh

然后执行。
kill -SIGSEGV 19365

你应该会看到类似这样的内容。
Segmentation fault (core dumped)

在您最初运行run.sh的终端窗口中执行以下操作。

最后,请执行

strings core

core 文件中。在某些字符串中,您应该看到您原始的 run.sh 文件的文本。

致谢:本答案改编自Retrieve plain text script from compiled bash script


Bash(有点奇怪)在执行期间会重新读取脚本,因此如果您在运行时删除脚本文件,则可能会导致其终止或死机。 - tripleee
1
@tripleee: 你说的有道理。请参见https://dev59.com/_msz5IYBdhLWcg3wiISe - Jonathan Ben-Avraham
所以我的意思是,证据表明Bash可能只在执行下一个块之前读取它,因此您不会在任何时候找到整个脚本加载到内存中,除非是非常简单的脚本。 - tripleee
@tripleee:在我看来,Bash 首先解析整个脚本文件,打印任何错误,然后执行。进行编辑、mv 或 rm 操作对你在核心转储中看到的脚本没有影响。你能提供一个反例吗? - Jonathan Ben-Avraham
这个仍然可以工作,即使run.sh有一个像这样的后台子shell:echo'(echo a; sleep 120; echo a)&' > run.sh - Sungam
显示剩余3条评论

2

bash 似乎会将其当前解释的脚本放在文件描述符255上,至少在我的系统上是这样的,在没有任何主动非默认约束文件描述符最大值等情况下。这可能不是保证的,因此您可能需要进行一些调整,但是,给定正在运行的 bash /some/script/sh 进程的PID,您可以查看 /proc/<PID>/fd/ 中的文件描述符链接 - 0、1和2当然是预定义的stdin/stdout/stderr,而其他的则取决于您的脚本所做的事情,但是通过筛选该目录的内容以找出哪个文件描述符对应于您的脚本文件,您就可以使用 cat 或其他方式(例如 cat /proc/12345/fd/255)查看原始脚本。


哇,我不知道那个。请参见这里这里。谷歌显示ksh也使用fd 10来实现相同的目的(所以它们似乎已经被固定下来了,但是不要依赖它。+1! - Adrian Frühwirth
谢谢@twalberg,这正是我想要的。但是,如果存在后台子shell echo'(echo a; sleep 120; echo a)&' > run.sh,它将无法工作。 - Sungam

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接