如何获取父 shell 之外的 PID 的退出代码?
How do I get the exit code of a PID outside of the parent shell?
背景
我正在尝试获取通过 x-terminal-emulator -e
启动的命令的退出代码。使用此命令,它只需打开一个新终端 window,然后将您希望在新终端 window 中执行的命令传递给它 sh -c
。然后我使用 ps ax, grep, xargs
和 cut
的组合来获取 运行 进程的 PID。
tester.sh
#!/bin/bash
execute() {
local -r CMDS=""
local exitCode=0
local cmdsPID=""
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
# Execute a command within a
# a new 'x-terminal-emulator' window.
x-terminal-emulator -e "$CMDS" &> /dev/null
# Get the PID of the process spawned by
# 'x-terminal-emulator'.
cmdsPID="$(ps ax | grep "sh -c $CMDS" | xargs | cut -d ' ' -f 1)"
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
# Wait for the commands to no longer be executing
# in the background, and then get their exit code.
wait "$cmdsPID" &> /dev/null
exitCode=$?
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
# Print output based on what happened.
echo "$exitCode"
}
execute "apt update && apt upgrade -y && apt full-upgrade -y && apt autoremove -y && apt clean"
⚠️错误
但是,当我使用命令wait
等待PID完成运行以便我可以获得命令的退出代码时,wait
returns:
pid #### is not a child of this shell
有没有一种方法既可以等待 PID 完成,又可以从未在父 shell 下生成的进程中获取其退出代码?
是否有理由在另一个 xterm 中启动您的命令?
您的脚本似乎是连续的,所以也许这个解决方案可以接受?
#!/bin/bash
execute() {
local -r CMDS=""
local exitCode=0
local cmdsPID=""
output=`$CMDS > /dev/null`
exitCode=$?
echo $exitCode
}
execute "apt update && apt upgrade -y && apt full-upgrade -y && apt autoremove -y && apt clean"
经过反复试验和一些研究,我想出了一个解决方案。
我的解决方案包括以下内容:
- 使用从
x-terminal-emulator
生成的新终端 window 中重定向 $?
输出到使用 mktemp
. 的临时文件
- 然后,利用
until
条件结构等待临时文件不为空。
- 一旦临时文件不为空,我就可以
cat
文件的内容并将其存储在一个变量中。然后,echo
结果。
tester.sh(重构)
#!/bin/bash
execute() {
local -r CMDS=""
local -r EXIT_STATUS_FILE="$(mktemp /tmp/XXXXX)"
local exitCode=0
local cmdsPID=""
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
# Execute a command within a
# a new 'x-terminal-emulator' window.
x-terminal-emulator -e "($CMDS) ; echo $? > $EXIT_STATUS_FILE" \
&> /dev/null
# Get the PID of the process spawned by
# 'x-terminal-emulator'.
cmdsPID="$(ps ax | grep -v "grep" | grep -v "S+" | grep "sh -c" | grep "$CMDS" | xargs | cut -d ' ' -f 1)"
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
# Wait for the commands to no longer be executing
# in the background, and then get their exit code.
until [ -s "$EXIT_STATUS_FILE" ];
do
sleep 1
done
exitCode="$(cat "$EXIT_STATUS_FILE")"
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
# Print output based on what happened.
echo "$exitCode"
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
# Remove temporary file.
rm -rf "$EXIT_STATUS_FILE"
}
execute \
"apt update && apt upgrade -y && apt full-upgrade -y && apt autoremove -y && apt clean"
为什么要使用另一个终端而不创建 child 进程?恕我直言,它更干净。这样你就可以使用等待命令:
function i_exit {
() &
wait $!
return $?
}
i_exit "true"
echo $?
i_exit "false"
echo $?
i_exit "true && true"
echo $?
i_exit "true && false"
echo $?
您使用“&”创建后台进程。创建的 PID 存储在 $!当 child 退出时,您可以 return 使用 $? 的值。这可以从具有相同变量的函数中捕获。上面的代码输出:
$ ./test.sh
0
1
0
0
不需要ps aux | grep whatever
!
编辑:
当然,如果您真的愿意,您可以在终端中执行操作。以下脚本就是这样做的。我没有 xfce,但你可以用 "x-terminal-emulator" 替换 "xterm"。
#! /bin/bash
function i_exit {
(xterm -e "") &
wait $!
return $?
}
# Waits 5 seconds
i_exit "true && echo 'Test 1' && sleep 5s"
echo $?
# Exits immediately
i_exit "false && echo 'Test 2' && sleep 5s"
echo $?
背景
我正在尝试获取通过 x-terminal-emulator -e
启动的命令的退出代码。使用此命令,它只需打开一个新终端 window,然后将您希望在新终端 window 中执行的命令传递给它 sh -c
。然后我使用 ps ax, grep, xargs
和 cut
的组合来获取 运行 进程的 PID。
tester.sh
#!/bin/bash
execute() {
local -r CMDS=""
local exitCode=0
local cmdsPID=""
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
# Execute a command within a
# a new 'x-terminal-emulator' window.
x-terminal-emulator -e "$CMDS" &> /dev/null
# Get the PID of the process spawned by
# 'x-terminal-emulator'.
cmdsPID="$(ps ax | grep "sh -c $CMDS" | xargs | cut -d ' ' -f 1)"
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
# Wait for the commands to no longer be executing
# in the background, and then get their exit code.
wait "$cmdsPID" &> /dev/null
exitCode=$?
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
# Print output based on what happened.
echo "$exitCode"
}
execute "apt update && apt upgrade -y && apt full-upgrade -y && apt autoremove -y && apt clean"
⚠️错误
但是,当我使用命令wait
等待PID完成运行以便我可以获得命令的退出代码时,wait
returns:
pid #### is not a child of this shell
有没有一种方法既可以等待 PID 完成,又可以从未在父 shell 下生成的进程中获取其退出代码?
是否有理由在另一个 xterm 中启动您的命令? 您的脚本似乎是连续的,所以也许这个解决方案可以接受?
#!/bin/bash
execute() {
local -r CMDS=""
local exitCode=0
local cmdsPID=""
output=`$CMDS > /dev/null`
exitCode=$?
echo $exitCode
}
execute "apt update && apt upgrade -y && apt full-upgrade -y && apt autoremove -y && apt clean"
经过反复试验和一些研究,我想出了一个解决方案。
我的解决方案包括以下内容:
- 使用从
x-terminal-emulator
生成的新终端 window 中重定向$?
输出到使用mktemp
. 的临时文件
- 然后,利用
until
条件结构等待临时文件不为空。 - 一旦临时文件不为空,我就可以
cat
文件的内容并将其存储在一个变量中。然后,echo
结果。
tester.sh(重构)
#!/bin/bash
execute() {
local -r CMDS=""
local -r EXIT_STATUS_FILE="$(mktemp /tmp/XXXXX)"
local exitCode=0
local cmdsPID=""
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
# Execute a command within a
# a new 'x-terminal-emulator' window.
x-terminal-emulator -e "($CMDS) ; echo $? > $EXIT_STATUS_FILE" \
&> /dev/null
# Get the PID of the process spawned by
# 'x-terminal-emulator'.
cmdsPID="$(ps ax | grep -v "grep" | grep -v "S+" | grep "sh -c" | grep "$CMDS" | xargs | cut -d ' ' -f 1)"
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
# Wait for the commands to no longer be executing
# in the background, and then get their exit code.
until [ -s "$EXIT_STATUS_FILE" ];
do
sleep 1
done
exitCode="$(cat "$EXIT_STATUS_FILE")"
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
# Print output based on what happened.
echo "$exitCode"
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
# Remove temporary file.
rm -rf "$EXIT_STATUS_FILE"
}
execute \
"apt update && apt upgrade -y && apt full-upgrade -y && apt autoremove -y && apt clean"
为什么要使用另一个终端而不创建 child 进程?恕我直言,它更干净。这样你就可以使用等待命令:
function i_exit {
() &
wait $!
return $?
}
i_exit "true"
echo $?
i_exit "false"
echo $?
i_exit "true && true"
echo $?
i_exit "true && false"
echo $?
您使用“&”创建后台进程。创建的 PID 存储在 $!当 child 退出时,您可以 return 使用 $? 的值。这可以从具有相同变量的函数中捕获。上面的代码输出:
$ ./test.sh
0
1
0
0
不需要ps aux | grep whatever
!
编辑: 当然,如果您真的愿意,您可以在终端中执行操作。以下脚本就是这样做的。我没有 xfce,但你可以用 "x-terminal-emulator" 替换 "xterm"。
#! /bin/bash
function i_exit {
(xterm -e "") &
wait $!
return $?
}
# Waits 5 seconds
i_exit "true && echo 'Test 1' && sleep 5s"
echo $?
# Exits immediately
i_exit "false && echo 'Test 2' && sleep 5s"
echo $?