Bash 终止进程未完成
Bash kill process misses up completion
我有一个 bash 主题,它以懒惰的方式显示提示的各个部分。所以它在开始时显示一组信息,然后从后台进程加载和重写提示需要时间的延迟加载信息。
现在,由于延迟加载的呈现是异步的,如果您从当前工作目录移动到另一个目录,而异步部分未呈现,我们将在错误的位置获得错误的信息。示例:
异步渲染函数调用者:
# Check the async side of the prompt if available
set +m
_render_async &
现在为了防止这种情况发生,我在呈现提示之前添加了一个检查以查看是否有任何后台进程正在等待呈现不在当前目录中的异步端并将其终止。
# Check and kill any irreelvant background jobs
# Outdated background jobs are any gaudi::async_render executed on folders
# other than the current working directory $PWD
export PROMPT_COMMAND="gaudi::kill_outdated_asyncRender; $PROMPT_COMMAND"
# Kill all background gaudi::render_async that are running in the wrong context
# Wrong context is any directory (CWD) that is not the current directory
# USAGE:
# gaudi::kill_outdated_asyncRender
gaudi::kill_outdated_asyncRender() {
joblist="$(jobs | grep '_render_async.*wd:' | cut -d "[" -f2 | cut -d "]" -f1 | tr '\n' ' ')"
IFS=' '
for job in $joblist; do kill "%$job"; done
}
这现在工作完美,我看不到错误的渲染,但我注意到现在 bash 函数的完成被搞砸了,项目没有显示,如下所示:
如您所见,完成元素不在同一行中,只是损坏了。删除 kill_outdated_asyncRender
修复了此行为,但我仍然不确定为什么会发生这种情况。
gaudi::kill_outdated_asyncRender
设置 IFS
,但不重置它。这具有全球影响,因为它在整个 bash 到 control word-splitting behavior:
中使用
The IFS variable is used in shells (Bourne, POSIX, ksh, bash) as the input field separator (or internal field separator). Essentially, it is a string of special characters which are to be treated as delimiters between words/fields when splitting a line of input.
修改 IFS
是一种常见模式,但您需要重新设置它:
gaudi::kill_outdated_asyncRender() {
joblist="$(jobs | grep '_render_async.*wd:' | cut -d "[" -f2 | cut -d "]" -f1 | tr '\n' ' ')"
local oIFS=$IFS
IFS=' '
for job in $joblist; do kill "%$job"; done
IFS=$oIFS
}
作为一般准则,请让您的 $PROMPT_COMMAND
简单明了。显然存在延迟问题,但它本身也很难调试。沿着这些思路,我会提出一些有针对性的建议,以减少副作用的可能性:
当您关闭后台进程时,将其 PID 记录到一个文件中。然后,在您的 kill 函数中使用此文件的内容,而不是 jobs | grep
管道。
不是在目录更改时计算这些值,而是在登录期间和定期(通过 cron)预先计算它们(在后台)。您还有一个同步更新值的 "refresh" 命令,因此如果您对所看到的内容有疑问,您始终可以获得最新值。
我有一个 bash 主题,它以懒惰的方式显示提示的各个部分。所以它在开始时显示一组信息,然后从后台进程加载和重写提示需要时间的延迟加载信息。
现在,由于延迟加载的呈现是异步的,如果您从当前工作目录移动到另一个目录,而异步部分未呈现,我们将在错误的位置获得错误的信息。示例:
异步渲染函数调用者:
# Check the async side of the prompt if available
set +m
_render_async &
现在为了防止这种情况发生,我在呈现提示之前添加了一个检查以查看是否有任何后台进程正在等待呈现不在当前目录中的异步端并将其终止。
# Check and kill any irreelvant background jobs
# Outdated background jobs are any gaudi::async_render executed on folders
# other than the current working directory $PWD
export PROMPT_COMMAND="gaudi::kill_outdated_asyncRender; $PROMPT_COMMAND"
# Kill all background gaudi::render_async that are running in the wrong context
# Wrong context is any directory (CWD) that is not the current directory
# USAGE:
# gaudi::kill_outdated_asyncRender
gaudi::kill_outdated_asyncRender() {
joblist="$(jobs | grep '_render_async.*wd:' | cut -d "[" -f2 | cut -d "]" -f1 | tr '\n' ' ')"
IFS=' '
for job in $joblist; do kill "%$job"; done
}
这现在工作完美,我看不到错误的渲染,但我注意到现在 bash 函数的完成被搞砸了,项目没有显示,如下所示:
如您所见,完成元素不在同一行中,只是损坏了。删除 kill_outdated_asyncRender
修复了此行为,但我仍然不确定为什么会发生这种情况。
gaudi::kill_outdated_asyncRender
设置 IFS
,但不重置它。这具有全球影响,因为它在整个 bash 到 control word-splitting behavior:
The IFS variable is used in shells (Bourne, POSIX, ksh, bash) as the input field separator (or internal field separator). Essentially, it is a string of special characters which are to be treated as delimiters between words/fields when splitting a line of input.
修改 IFS
是一种常见模式,但您需要重新设置它:
gaudi::kill_outdated_asyncRender() {
joblist="$(jobs | grep '_render_async.*wd:' | cut -d "[" -f2 | cut -d "]" -f1 | tr '\n' ' ')"
local oIFS=$IFS
IFS=' '
for job in $joblist; do kill "%$job"; done
IFS=$oIFS
}
作为一般准则,请让您的 $PROMPT_COMMAND
简单明了。显然存在延迟问题,但它本身也很难调试。沿着这些思路,我会提出一些有针对性的建议,以减少副作用的可能性:
当您关闭后台进程时,将其 PID 记录到一个文件中。然后,在您的 kill 函数中使用此文件的内容,而不是
jobs | grep
管道。不是在目录更改时计算这些值,而是在登录期间和定期(通过 cron)预先计算它们(在后台)。您还有一个同步更新值的 "refresh" 命令,因此如果您对所看到的内容有疑问,您始终可以获得最新值。