【问题标题】:Bash script exits with no errorBash 脚本退出且没有错误
【发布时间】:2013-06-14 11:15:00
【问题描述】:

我有一个从 DVD 运行的 bash 脚本。此脚本将多卷 tar 文件从 DVD 复制到本地计算机。在复制过程中,脚本提示用户插入第二张 DVD,此时剩余的文件将被复制。该脚本存在于第一张 DVD 上,但不存在于第二张 DVD 上。

此脚本只是在复制最后一个文件后停止,但在开始 tar 多卷提取操作和后续处理之前。没有报告错误或消息。我试过用'-x'运行bash,但没有什么可疑的——甚至没有退出语句。更不幸的是,这种行为是不一致的。有时脚本会停止,但有时会继续运行而没有问题。

我已经在脚本上运行了 strace。复制操作结束后,我看到:

read(255, "\0\0\0\0\0\0\0\0\0\0"..., 5007) = 1302
read(255, "", 5007)       = 0
exit_group(0)             = ?

我知道 bash 将脚本文件读入内存并从那里执行,但它是否有可能在某个时候尝试重新读取脚本文件并失败(因为它不再存在)? tar 文件非常大,从脚本启动到最后一个文件被复制(从第二张 DVD)大约需要 10-15 分钟。

【问题讨论】:

  • dmesg 中是否有任何内容表明您内存不足或类似情况?我倾向于尝试修改脚本以将自身复制到本地存储,并从那里执行自身。
  • 感谢您的建议。我会检查dmesg。我实际上曾考虑将脚本复制到 /tmp 然后从那里重新调用它。我唯一担心的是父脚本仍然是从 DVD 执行的。据推测,bash 不会尝试重新读取父脚本,直到子脚本退出(此时我已经完成了)。
  • 我只是能够重现它。 dmesg 中没有任何内容。有趣的是,我在运行“cat /dev/zero > /dev/shm/file”并在 vi 中打开一个非常大的日志文件以尽可能多地使用内存时复制了它(我的内存减少到 32M!) .我不确定是这些原因造成的,还是我只是幸运,但值得注意。我将修改脚本以将其自身复制到 /tmp,然后从那里重新运行它。然后,我会重新测试。我们会看看会发生什么。

标签: linux bash shell tar strace


【解决方案1】:

我看到您已经找到了解决方法,所以我将尝试找出正在发生的事情:

bash 并没有将整个脚本读入内存,而是对其进行缓冲读取,每次只进行必要的读取(大概是为了与终端输入共享代码)。在启动任何外部命令之前,bash 会寻找脚本中的确切位置,并在命令完成后继续从那里读取。如果您在运行时编辑脚本文件,您可以看到它:

term1$ cat > test.sh
sleep 8
echo DONE
term1$ bash test.sh

sleep 正在执行时,从另一个终端更改脚本:

term2$ cat > test.sh
echo HAHA

观察bashsleep 完成后如何变得混乱:

test.sh: line 2: A: command not found

它记得输入文件中的位置是 sleep 之前的 8,因此它尝试从那里读取并遇到覆盖脚本中的最后一个 A

现在谈谈你的情况。通常,从 dvd 打开文件会锁定驱动器并禁止更改磁盘。如果您仍然设法更改磁盘,那肯定会涉及一个 umount,这应该会使脚本 fd 无效。根据您的strace 输出,这显然不会发生,这有点奇怪。无论如何,bash 将无法读取脚本的其余部分。

【讨论】:

  • 我认为你是完全正确的。我能找到的所有证据都支持这一点。到目前为止,我的解决方法似乎正在奏效。谢谢!
  • 我会说,bash 没有报告任何类型的错误是很奇怪的。你会认为他们可以打印一条读取失败的消息。
  • 是的,但是您的 strace 显示它没有失败!那是奇怪的部分......它只是返回了一堆零,然后被 bash 忽略并命中 EOF。
猜你喜欢
  • 2017-12-03
  • 1970-01-01
  • 1970-01-01
  • 2011-02-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-07-29
相关资源
最近更新 更多