AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / unix / 问题 / 506244
Accepted
user3901666
user3901666
Asked: 2019-03-15 01:43:03 +0800 CST2019-03-15 01:43:03 +0800 CST 2019-03-15 01:43:03 +0800 CST

unix 中 nohup 命令的退出代码问题

  • 772

我一直在试图弄清楚如何捕获 nohup 命令的退出状态,然后根据状态发送邮件。

下面是我的代码:

if [[ "" !=  "$PID" ]]; then
    echo "killing $PID"
    kill -9 $PID
    nohup java -jar Xyz-port-0.0.1.jar &
    << Exit Code and then send mail if Exit 
      code is 0>>
    else 
    echo "Process doesn't exist"
    fi
linux shell-script
  • 3 3 个回答
  • 5096 Views

3 个回答

  • Voted
  1. Kusalananda
    2019-03-15T02:10:23+08:002019-03-15T02:10:23+08:00

    后台作业总是成功启动:

    $ sntaoehu &
    [1] 33566
    $ bash: sntaoehu: command not found
    [1]+  Exit 127                sntaoehu
    $ echo $?
    0
    

    nohup在命令终止之前,您无法在后台启动您的 Java 程序并检测它是否运行良好。nohup如果找不到或无法启动java,或者当 Java 程序终止时,该命令将终止。它不是nohup在后台运行您的程序。它只是让您的程序忽略任何HUP信号并一直挂起,直到您的程序终止,然后它将程序的退出状态返回给调用 shell。

    如果作业启动失败,要发送电子邮件,您可以这样做

    (
        nohup java -jar Xyz-port-0.0.1.jar
        status=$?
        if [ "$status" -eq 126 ] || [ "$status" -eq 127 ]; then
            # something wrong in launching java
            echo 'nohup failed to run java'
            printf 'nohup exit status is %s\n' "$status"
        elif [ "$status" -ne 0 ]; then
            # the java code returned an error
            echo 'java returned an error'
            printf 'java exit status is %s\n' "$status"
        else
            # everything went well and java exited ok
            echo 'java exited safely'
        fi | mail -s 'java job status report' [email protected]
    ) &
    
    echo 'started background job'
    

    即,启动您运行程序的后台子shell,然后测试返回的是126 还是127。如果找不到或无法启动命令nohup,它将执行此操作。java

    • 2
  2. Best Answer
    111---
    2019-03-15T04:39:06+08:002019-03-15T04:39:06+08:00

    这样的事情将更可靠地捕获您的进程的退出代码:

    父.sh

    ...
    java -jar Xyz-port-0.0.1.jar > /dev/null & #optionally discard stdout of java
    child=$!
    wait $child
    exit_status=$?
    if [[ "$exit_status" -ne 0 ]]; then
        # handle error
    else
        #handle success
    fi
    

    等待

    请注意,调用wait将无限期阻塞,因此,如果您需要对java完成命令的时间量设置任意限制,您可以将调用替换为wait循环并进行一些手动检查ps以查看它,该过程仍在跑步。这将允许您设置一个看门狗并在进程挂起时将所有人从池中调用。

    诺胡普

    如果您需要在不处于活动终端会话中的情况下运行 java 进程并处理其退出代码,请nohup不使用java代码调用您的父脚本(上图)。父脚本可以被nohup编辑,并且可以在没有控制终端的情况下在后台运行,并且可以可靠地进行电子邮件发送或清理。

    • 1
  3. telcoM
    2019-03-15T02:20:43+08:002019-03-15T02:20:43+08:00

    问题不一定是nohup命令,而是&命令行末尾的问题。

    手册页bash说:

    如果命令由控制运算符 & 终止,则 shell 在子 shell 的后台执行命令。shell 不等待命令完成,返回状态为 0。

    从技术上讲,shell 派生出一个子 shell 来执行nohup ...命令,执行脚本的主 shell 立即继续执行脚本中的下一个命令。因此,当主 shell 执行该行之后的nohup ... &行时,nohup 命令可能尚未退出:子 shell 可能正在加载它以执行。

    并且该nohup命令不一定就这样退出:它设置信号处理程序以忽略 HUP 信号,然后尝试直接exec()执行该java ...命令。如果exec()系统调用成功,那么被nohup转换成的进程java 没有fork()新进程退出,所以还没有退出代码返回。

    nohup实际命令返回退出代码的唯一方法是java无法找到或执行该命令,或者该nohup命令本身存在内部错误。如果exec()系统调用成功,退出代码可用的唯一时间是java命令本身结束时。

    这也是为什么尝试这样的事情并不能达到你想要的效果:

    nohup java -jar Xyz-port-0.0.1.jar &
    wait $! 
    if [ $? -ne 0 ]; then
        echo "Error in running Java"
    fi
    

    如果nohup在后台失败,wait将获取其退出代码并允许对其进行检查;但是如果nohup启动成功java,那么wait命令将一直等待直到java退出,因为两者都nohup将java在同一个进程中一个接一个地运行。

    正如@datUser 建议的那样,您可能想做这样的事情:

    STARTWAIT=20 #number of seconds to wait after starting the service
    
    nohup java -jar Xyz-port-0.0.1.jar &
    NEWPID=$!
    for i in $(seq $STARTWAIT); do
        # test if the process still exists
        if ! kill -0 $NEWPID 2>/dev/null; then
            # Process has died: get its exit code, report error, stop waiting
            wait $!
            EXITCODE=$?
            echo "Process died after restart and reported result $EXITCODE" >&2
            break
        fi
        sleep 1
    done
    if kill -0 $NEWPID; then
        echo "The process was started and is still alive after $STARTWAIT seconds"
        echo "so I guess it's now running correctly"
    fi
    

    请注意,我的脚本解决方案有一个固有的弱点:如果nohupped 进程死亡而另一个进程在一秒钟内收到相同的 PID 号,则该脚本将无法注意到它不再是同一个进程。(但如果你的 PID 号码回收得那么快,你可能会遇到更大的问题。)

    为了最佳地解决问题,您需要脚本设置某种超时机制,该机制将wait在某个预定时间停止命令,然后wait()在受监控的进程上运行系统调用(通过waitshell 命令),因为这是只有被​​监视进程的实际父进程才能执行的操作。这在 shell 脚本中实现起来非常棘手。

    • 0

相关问题

  • 通过命令的标准输出以编程方式导出环境变量[重复]

  • 按分隔符拆分并连接字符串问题

  • astyle 不会更改源文件格式

  • MySQL Select with function IN () with bash array

  • 通过标签将根文件系统传递给linux内核

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    模块 i915 可能缺少固件 /lib/firmware/i915/*

    • 3 个回答
  • Marko Smith

    无法获取 jessie backports 存储库

    • 4 个回答
  • Marko Smith

    如何将 GPG 私钥和公钥导出到文件

    • 4 个回答
  • Marko Smith

    我们如何运行存储在变量中的命令?

    • 5 个回答
  • Marko Smith

    如何配置 systemd-resolved 和 systemd-networkd 以使用本地 DNS 服务器来解析本地域和远程 DNS 服务器来解析远程域?

    • 3 个回答
  • Marko Smith

    dist-upgrade 后 Kali Linux 中的 apt-get update 错误 [重复]

    • 2 个回答
  • Marko Smith

    如何从 systemctl 服务日志中查看最新的 x 行

    • 5 个回答
  • Marko Smith

    Nano - 跳转到文件末尾

    • 8 个回答
  • Marko Smith

    grub 错误:你需要先加载内核

    • 4 个回答
  • Marko Smith

    如何下载软件包而不是使用 apt-get 命令安装它?

    • 7 个回答
  • Martin Hope
    user12345 无法获取 jessie backports 存储库 2019-03-27 04:39:28 +0800 CST
  • Martin Hope
    Carl 为什么大多数 systemd 示例都包含 WantedBy=multi-user.target? 2019-03-15 11:49:25 +0800 CST
  • Martin Hope
    rocky 如何将 GPG 私钥和公钥导出到文件 2018-11-16 05:36:15 +0800 CST
  • Martin Hope
    Evan Carroll systemctl 状态显示:“状态:降级” 2018-06-03 18:48:17 +0800 CST
  • Martin Hope
    Tim 我们如何运行存储在变量中的命令? 2018-05-21 04:46:29 +0800 CST
  • Martin Hope
    Ankur S 为什么 /dev/null 是一个文件?为什么它的功能不作为一个简单的程序来实现? 2018-04-17 07:28:04 +0800 CST
  • Martin Hope
    user3191334 如何从 systemctl 服务日志中查看最新的 x 行 2018-02-07 00:14:16 +0800 CST
  • Martin Hope
    Marko Pacak Nano - 跳转到文件末尾 2018-02-01 01:53:03 +0800 CST
  • Martin Hope
    Kidburla 为什么真假这么大? 2018-01-26 12:14:47 +0800 CST
  • Martin Hope
    Christos Baziotis 在一个巨大的(70GB)、一行、文本文件中替换字符串 2017-12-30 06:58:33 +0800 CST

热门标签

linux bash debian shell-script text-processing ubuntu centos shell awk ssh

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve