在这篇文章中,我们将带领您了解确定Java关闭挂钩线程中的退出状态的全貌,包括确定java关闭挂钩线程中的退出状态的方法的相关情况。同时,我们还将为您介绍有关awk–如何在getline管道中获取命令
在这篇文章中,我们将带领您了解确定Java关闭挂钩线程中的退出状态的全貌,包括确定java关闭挂钩线程中的退出状态的方法的相关情况。同时,我们还将为您介绍有关awk – 如何在getline管道中获取命令的退出状态?、bash – 使用set -e为程序的退出状态提供通用解决方案、Bash“not”:反转命令的退出状态、bash中的退出状态机制的知识,以帮助您更好地理解这个主题。
本文目录一览:- 确定Java关闭挂钩线程中的退出状态(确定java关闭挂钩线程中的退出状态的方法)
- awk – 如何在getline管道中获取命令的退出状态?
- bash – 使用set -e为程序的退出状态提供通用解决方案
- Bash“not”:反转命令的退出状态
- bash中的退出状态机制
确定Java关闭挂钩线程中的退出状态(确定java关闭挂钩线程中的退出状态的方法)
我想确定关闭挂钩运行时过程的退出状态。
我想有一个基于状态码(0或非零)的逻辑
(例如:如果零不执行其他操作,则非零则发送警报电子邮件)
您知道我如何获得此信息吗?
答案1
小编典典我试图覆盖该SecurityManager
checkExit(int status)
方法-
如果System.exit(status)
在任何地方都显式调用此方法,则该方法有效-
但是,当应用程序“正常”退出(无活动线程)或错误导致VM退出时,它不会设置状态。
import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;import java.security.Permission;public class ExitChecker { public ExitChecker() { System.setSecurityManager(new ExitMonitorSecurityManager()); Runtime.getRuntime().addShutdownHook(new Thread(new MyShutdownHook())); BufferedReader input = new BufferedReader(new InputStreamReader(System.in)); String line = ""; while (!line.equalsIgnoreCase("Q")) { try { System.out.println("Press a number to exit with that status."); System.out.println("Press ''R'' to generate a RuntimeException."); System.out.println("Press ''O'' to generate an OutOfMemoryError."); System.out.println("Press ''Q'' to exit normally."); line = input.readLine().trim(); processInput(line); } catch (IOException e) { e.printStackTrace(); System.exit(-1); } } } private void processInput(String line) { if (line.equalsIgnoreCase("Q")) { // continue, will exit loop and exit normally } else if (line.equalsIgnoreCase("R")) { throwRuntimeException(); } else if (line.equals("O")) { throwError(); } else { // try to parse to number try { int status = Integer.parseInt(line); callExit(status); } catch(NumberFormatException x) { // not a number.. repeat question... System.out.println("\nUnrecognized input...\n\n"); } } } public void callExit(int status) { System.exit(status); } public void throwError() { throw new OutOfMemoryError("OutOfMemoryError"); } public void throwRuntimeException() { throw new RuntimeException("Runtime Exception"); } public static void main(String[] args) { new ExitChecker(); } private static class ExitMonitorSecurityManager extends SecurityManager { @Override public void checkPermission(Permission perm) { //System.out.println(perm.getName()); //System.out.println(perm.getActions()); } @Override public void checkPermission(Permission perm, Object context) { //System.out.println(perm.getName()); //System.out.println(perm.getActions()); } @Override public void checkExit(int status) { System.out.println("Setting exit value via security manager..."); MyShutdownHook.EXIT_STATUS = status; } } private static class MyShutdownHook implements Runnable { public static Integer EXIT_STATUS; public void run() { System.out.println("In MyShutdownHook - exit status is " + EXIT_STATUS); } }}
awk – 如何在getline管道中获取命令的退出状态?
例如,假设我有一个名为foo.awk的awk脚本,如下所示:
function close_and_get_exit_status(cmd) { # magic goes here... } BEGIN { cmd = "echo foo; echo bar; echo baz; false" while ((cmd | getline line) > 0) print "got a line of text: " line if (close_and_get_exit_status(cmd) != 0) { print "ERROR: command '" cmd "' Failed" | "cat >&2" exit 1 } print "command '" cmd "' was successful" }
然后我希望发生以下情况:
$awk -f foo.awk got a line of text: foo got a line of text: bar got a line of text: baz ERROR: command 'echo foo; echo bar; echo baz; false' Failed $echo $? 1
根据POSIX specification for awk,命令| getline为成功输入返回1,为文件结束返回0,为错误返回-1.如果命令以非零退出状态退出,则不是错误,因此不能用于查看命令是否已完成且失败.
类似地,close()不能用于此目的:close()仅在关闭失败时返回非零,而不是在关联命令返回非零退出状态时返回非零. (在gawk中,close(命令)返回命令的退出状态.这是我想要的行为,但我认为它违反了POSIX规范,并不是所有的awk实现都是这样的.)
awk system()函数返回命令的退出状态,但据我所知,没有办法使用getline.
解决方法
$cat tst.awk BEGIN { cmd = "echo foo; echo bar; echo baz; false" mod = cmd "; echo \"$?\"" while ((mod | getline line) > 0) { if (numLines++) print "got a line of text: " prev prev = line } status = line close(mod) if (status != 0) { print "ERROR: command '" cmd "' Failed" | "cat >&2" exit 1 } print "command '" cmd "' was successful" } $awk -f tst.awk got a line of text: foo got a line of text: bar got a line of text: baz ERROR: command 'echo foo; echo bar; echo baz; false' Failed $echo $? 1
如果有人正在阅读此内容并考虑使用getline,请务必阅读http://awk.freeshell.org/AllAboutGetline并完全理解所有注意事项以及首先要做的事情.
bash – 使用set -e为程序的退出状态提供通用解决方案
当它是我使用||如果我不需要退出代码.
如果我需要退出代码,我将执行包装如下:
set +e call_I_need_the_exit_code with few arguments RV="$?" set -e # use "$RV" somewhat
但是,它很冗长,我很少切换设置e和设置-e引入恼人的错误.
有没有办法创建一个执行命令的函数,并为退出代码设置一个已知变量?
像这样的东西(伪代码):
safe_call( call_I_need_the_exit_code(with,few,arguments) ) # use "$RV" somewhat
其中safe_call基本上是前一段代码.这将使我的代码更容易编写和阅读…
command && rv=0 || rv=$?
另外,你应该avoid uppercase for your private variables.
Bash“not”:反转命令的退出状态
if diff -q $f1 $f2 then echo "they're the same" else echo "they're different" fi
但是,如果我想否定我正在检查的条件呢?即这样的事情(显然不起作用)
if not diff -q $f1 $f2 then echo "they're different" else echo "they're the same" fi
我可以这样做……
diff -q $f1 $f2 if [[ $? > 0 ]] then echo "they're different" else echo "they're the same" fi
我在哪里检查前一个命令的退出状态是否大于0.但这感觉有点尴尬.有没有比较惯用的方法呢?
if ! diff -q $f1 $f2; then ...
bash中的退出状态机制
程序的退出状态
当一个程序结束时会向父进程报告自己的退出状态( exit status
). 通过传递 int
类型的变量给库函数 exit
或系统调用 _exit
可以设置当前程序的退出状态, 在 Linux
中, 通过 WEXITSTATUS
返回的退出状态的值域为 [0, 255]
之间的整数 . 如果传递的值不在这个范围内, 内核会自动帮你强转为 u_int8_t
. 通过 waitpid
库函数可以得到子进程的退出状态, 其值存储在参数 wstatus
的低 8
位中.
// 定义在 wait.h 中
# define WEXITSTATUS(status) __WEXITSTATUS (status)
// 定义在 waitstatus.h 中
/* If WIFEXITED(STATUS), the low-order 8 bits of the status. */
#define __WEXITSTATUS(status) (((status) & 0xff00) >> 8)
下面这个例子展示了如何使用 waitpid
及相关宏函数获取子进程的退出状态:
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
#define PARENT_EXIT 10086
#define CHILD_EXIT -10
int main()
{
pid_t pid = fork();
if (pid > 0)
{
int wstatus;
// 父进程等待子进程执行完毕, 用 WUNTRACED 选项追踪已结束的子进程
pid_t child_pid = waitpid(pid, &wstatus, WUNTRACED);
if (WIFEXITED(wstatus))
printf("Child exit status: %d\n", WEXITSTATUS(wstatus));
else
perror("Bad wait status\n");
// 父进程退出
exit(PARENT_EXIT);
}
else if (pid == 0)
{
// 子进程立即退出, 因此需要父进程设置 WUNTRACED
exit(CHILD_EXIT);
}
else
{
// 处理 fork 时出现的错误
perror("fork\n");
exit(EXIT_FAILURE);
}
}
编译并运行上例可以得到被强转后的状态码, 我们使用 WIFEXITED
判断等待的子进程是否执行成功, 然后对执行成功子进程使用 WEXITSTATUS
获取其退出状态. 对程序来说, 最终的退出状态就是主进程的退出状态.
> gcc ecitcode.c;./a.out;echo "Parent exit status: $?"
Child exit status: 246 # -10 强转为 uint8
Parent exit status: 102 # 10086 强转为 uint8
在 POSIX
标准中规定退出状态 0
代表该程序正常退出, 1
代表发生错误, 其他数字由程序自行规定, 因此在 glibc
的 stdlib.h
中仅定义了如下宏:
#define EXIT_FAILURE 1 /* Failing exit status. */
#define EXIT_SUCCESS 0 /* Successful exit status. */
程序本身一般会在文档中事先约定每种退出状态代表的退出原因( termination
), 例如在 ls
的帮助文档中:
> ls --help
...其他内容...
Exit status: # 退出状态
0 if OK, # 正常执行
1 if minor problems # 次要问题, 例如: 无法访问子目录
2 if serious trouble # 严重错误, 例如: 无法访问命令行参数
...其他内容...
命令的退出状态
在 bash
中会记录所执行命令的退出状态, 可以通过 $?
获取最近执行的命令的退出状态. bash
自身的退出状态为执行的最后一条命令的退出状态, 也就等价于显式指定 exit $?
. 如果没有执行任何命令就退出, 则 bash
的退出状态为 0
, 要注意在 bash
中用 0
表示 true
, 用非零表示 false
.
# 用 exit 显式指定退出状态
> bash
> exit 98
exit
> echo $?
98
# 什么也不执行则退出状态为 0
> bash
exit # Ctrl + D 退出
> echo $?
0
# 默认为最后一条命令的退出状态
> bash
> ecasd
ecasd: command not found
exit # Ctrl + D 退出
> echo $?
127
在 bash
中对不同种类命令的退出状态作出如下规定:
内置命令: 由于内置命令执行时不需要启动额外的子进程, 因此需要用返回值模拟退出状态. 每个函数都定义了自己的退出状态, 例如: 内置命令 source
将脚本文件的最后一个命令的返回状态作为命令的返回状态. bash
中所有的内置命令都用退出状态 2
表示用法错误, 例如: 选项错误, 缺少参数.
> cd -+- # 错误的参数
bash: cd: -+: invalid option
cd: usage: cd [-L|[-P [-e]] [-@]] [dir]
> echo $?
2
外部命令: 外部命令的退出状态就是使用 waitpid
得到的子进程的退出状态, 如果子进程在执行过程被编号为 N
的信号所终止, 则得到的退出状态就为 128+N
.
Shell 函数: 定义 shell
函数时, 函数名与之前已定义的只读函数名相同则退出状态为 1
, 当发生语法错误则退出状态为 2
. 执行 shell
函数时, 函数中最后执行的一条命令的退出状态就是整个函数的退出状态.
# 二次定义只读函数报错
> func () { echo; }
> readonly -f func
> func; echo $?
0
> func () { echo poi; }
bash: func: readonly function
> echo $?
1
# 定义函数发生语法错误
> fune () {aa}
bash: syntax error near unexpected token ''{aa}''
> echo $?
2
# 函数的退出状态是最后执行的命令的退出状态
> funr () { echo; return 6; }
> funr; echo $?
# echo 打印的空行
6 # return 6 是函数中最后执行的命令
表达式: 使用 ((...))
或 let
修饰的表达式的退出状态取决于表达式的值, 如果表达式的值为 0
则退出状态为 1
; 如果表达式的值为非零, 则退出状态为 0
.
> let 0+0; echo $?
1 # 表达式值为零
> ((7-5)); echo $?
0 # 表达式值非零
命令列表: 用 ;
, &
, &&
, ||
连接命令被称为命令列表, 其中用 &&
和 ||
连接的命令使用左关联( left associativity
)模式执行列表中的命令. 整个命令列表的退出状态为最后一条命令的退出状态. 此外, $( LISTS )
以及流程控制结构如: for
, while
等的返回状态也是结构中的命令列表的退出状态.
# 功能: 能ping通baidu.com则输出 `baidu.com is up` , 否则输出 `baidu.com is down` 。
> ping -c1 baidu.com &> /dev/null && echo ''baidu.com is up'' || echo ''baidu.com is down''
baidu.com is down
> echo $?
0 # 无论是否能 ping 通, 命令列表的退出状态都等于最后一条命令的退出状态
左关联模式被广泛应用于各种语言的逻辑运算符优化中. 对于逻辑与运算符&&
, 以eq1 && eq2
为例, 只有当两边都为True
才会返回True
, 因此当eq1
为False
时,eq2
不会执行; 对于逻辑或运算符||
, 以eq1 || eq2
为例, 只要两边有一个True
就会返回True
, 因此当eq1
为True
时,eq2
不会执行。
脚本: 使用 .
或 source
运行脚本文件等同于在当前 bash
中执行代码块, 脚本中最后执行的命令的退出状态就是脚本的退出状态. 使用 ./脚本名
或 bash 脚本名
的方式执行脚本文件等同于执行外部命令, 脚本的退出状态就是外部命令 bash
的退出状态. 如果脚本中最后执行的命令是 exit
, 那么使用 .
或 source
执行该脚本文件在执行结束后会退出当前 bash
.
后台作业与协作进程: 使用不带选项的 wait
命令可以获得最后一个执行完毕的后台作业的退出状态, 如果使用 wait -n <jobsec>
可以获得指定后台作业的退出状态, 如果作业不存在则退出状态为 127
. 使用 coproc
在 sub shell
中执行的命令的退出状态和后台作业一样可以被 wait
获取, coproc
自身的退出状态始终为 0
.
> { sleep 10; aad; } &
[1] 558
> wait -n 1
[1]+ Exit 127 { sleep 10; aad; }
> coproc { sleep 10; aad; }
[1] 558
> echo $?
0 # 这是 coproc 的执行结果
> jobs
[1]+ Exit 127 coproc COPROC { sleep 10; aad; }
管道命令: 默认情况下, 管道的退出状态取决于管道中最后一条命令的退出状态. 如果设置了 set -o pipefail
, 那么只有在管道中的全部命令的退出状态为 0
时, 整个管道的退出状态才为 0
, 否则就是最后一个非零的退出状态. 在管道前添加 !
符号可以对整个管道的退出状态取反. bash
中的特殊变量 $PIPESTATUS
以数组的形式存储最近执行的前台管道的退出状态, 要注意的是单个命令也会被记录, 也就是说 ${PIPESTATUS[0]}
和 $?
是等价的.
# 管道的退出状态是最后一条命令的退出状态
> ps | xxp 2>/dev/null | cat; echo $?
0
> set -o pipefail
> ps | xxp 2>/dev/null | cat; echo $?
127 # 设置了 pipefail 因此得到最后一个非零退出状态
# 管道中每个命令的退出状态被按顺序记录在数组中
> easd 2>/dev/null | ls /nou 2>/dev/null | more 2>/dev/null
> echo ${PIPESTATUS[@]}
127 2 0
# 不带管道符号的单个命令也会被记录
> ping asbasdasd 2>/dev/null; echo ${PIPESTATUS[0]}
2
> ping asbasdasd 2>/dev/null; echo $?
2
参考资料
- Exit status range
- Bash man page
关于确定Java关闭挂钩线程中的退出状态和确定java关闭挂钩线程中的退出状态的方法的介绍已经告一段落,感谢您的耐心阅读,如果想了解更多关于awk – 如何在getline管道中获取命令的退出状态?、bash – 使用set -e为程序的退出状态提供通用解决方案、Bash“not”:反转命令的退出状态、bash中的退出状态机制的相关信息,请在本站寻找。
本文标签: