0

我有一个服务器设置,我们使用 git 作为部署工具。它检出单个bash文件post-receive,然后执行它。

bash脚本假设通过执行来停止进程echo "" > fifo_file

当有人通过 SSH 登录到服务器并手动调用时,这非常有效bash_script.sh,在这种情况下,所有进程都将停止,代码部署并启动新进程。

但是由 执行的完全相同的序列post-receive并不完全有效。旧进程在重新启动后仍然存在,因此它们占用了新部署的代码工作所需的端口。

那里可能有什么问题?

4

2 回答 2

0

我有一个类似的问题,但首先,我会给你一些提示来调试你的问题:

  • 查看您的流程层次结构以了解是否存在不应该存在的流程。ps faux

  • 如果一个进程挂在某个东西上,而您不知道是什么,您可以strace -p <PID>查看阻塞该进程的系统调用

  • 如果这是关于文件描述符(在读取或写入调用时阻塞),那么您可以使用查看该进程的文件描述符lsof -p <PID>

  • 现在,如果您想查看其他进程正在使用此文件描述符,您可以查看NODE列上的数字并运行:lsof | grep <NODE>

我遇到的问题是钩子脚本的标准输出和标准错误被 git 捕获在管道中,以将它们转发到远程主机(执行 git push 的主机)。此外,我的脚本重新启动了 postgresql 守护进程。因此,postgresql 继承了 git 的标准输出和标准错误。也就是说,将所有内容转发回远程命中主机的管道。

一种解决方案是在生成服务时关闭 stdout 和 stderr,例如:

service postgresql restart >&- 2>&- <&-

但是,您不会收到任何错误消息。我犯规的另一个更通用的解决方案是将以下代码放入我的更新后挂钩中:

# Creates a temp file
t="$(tempfile)" || exit
trap "rm -f -- '$t'" EXIT

# Run the script
# You need to run the script in background, and to redirect its standard and
# error output to $t
bash path/to/script.bash >"$t" 2>&1 </dev/null &

# use tail -f to follow the output of the script, and --pid to exit when the
# previous script exits ($! is the pid of the script). This might not be very
# portable though
tail -n 0 --pid $! -f "$t"

# Clean up temp file
# if a process is still attached to it, the inode won't be cleared until the
# process close the file or dies. In our case, we don't care much.
rm -f -- "$t"
trap - EXIT
于 2013-01-14T16:02:47.597 回答
0

您有一个脚本 bash_script.sh,它正在执行几个步骤。如果已经被钩子触发,那么第一步(通过写入 fifo 文件来停止进程)似乎不起作用。

让我们忽略以下步骤并专注于第一步。

文件系统中有一个fifo文件。一方面,该fifo有一个写入过程。在另一端,有另一个进程从该 fifo 读取并触发您的进程关闭。

该先进先出几乎完全分离了双方,因此任何细微的差异,如第一个进程的 shell 模式或环境变量都与第二个进程无关。

唯一的一点是,您需要访问正确的文件,并且需要写入权限。

一些想法:

  • 确保通过绝对路径(以 / 开头)访问文件。否则,您可能只是写入错误的文件。;)
  • 确保您的 fifo 具有适当的访问权限。——但应该已经是这样了。
  • 添加一点调试。
    • 是否完全触发了部署脚本?
    • 你有没有抱怨什么?
    • id;pwd;ls -ld $fifo在钩子中添加类似的东西。

这应该给你一个提示是怎么回事。

于 2012-12-03T23:01:19.533 回答