【问题标题】:Easy way to get result status code of "systemd-run <command>"?获取“systemd-run <command>”结果状态代码的简单方法?
【发布时间】:2015-08-08 07:55:37
【问题描述】:

看来systemd-run &lt;command&gt; 的结果状态码总是0,除非调用运行时systemd 单元失败。

示例 1:

$ sudo systemd-run /usr/bin/true
Running as unit run-12255.service.
$ echo $?
0

$ sudo systemd-run /usr/bin/false
Running as unit run-12258.service.
$ echo $?
0

我可以知道命令是否成功执行如下。

示例 2:

$ systemctl status $(sudo systemd-run /usr/bin/true 2>&1 | awk '{ print $4 }' | sed -e 's/\.$//')
● run-13004.service
   Loaded: not-found (Reason: No such file or directory)
   Active: inactive (dead)
$ echo $?
3

$ systemctl status $(sudo systemd-run /usr/bin/false 2>&1 | awk '{ print $4 }' | sed -e 's/\.$//')
● run-13021.service - /usr/bin/false
   Loaded: loaded (/run/systemd/system/run-13021.service; static; vendor preset: disabled)
  Drop-In: /run/systemd/system/run-13021.service.d
           └─50-Description.conf, 50-ExecStart.conf
   Active: failed (Result: exit-code) since Sat 2015-08-08 07:31:10 UTC; 15ms ago
  Process: 13024 ExecStart=/usr/bin/false (code=exited, status=1/FAILURE)
 Main PID: 13024 (code=exited, status=1/FAILURE)
$ echo $?
3

但是返回的代码总是3,因为它是systemctl status 命令的结果。 最后,我必须做到以下几点;

示例 3:

$ systemctl status $(sudo systemd-run /usr/bin/true 2>&1 | awk '{ print $4 }' | sed -e 's/\.$//') | (egrep -m 1 -o 'code=exited, status=[0-9]+'| egrep -o '[0-9]+') || echo '0'
0

$ systemctl status $(sudo systemd-run /usr/bin/false 2>&1 | awk '{ print $4 }' | sed -e 's/\.$//') | (egrep -m 1 -o 'code=exited, status=[0-9]+'| egrep -o '[0-9]+') || echo '0'
1

这太奇怪了!

我之所以使用systemd-run 并获得返回码,是因为我想在正在运行的systemd-nspawned 容器环境中执行一个或多个命令(by systemd-run --machine=my_container)。

总而言之,我想在systemd-nspawned 容器中执行一个命令,并像docker exec 一样获得结果代码(没有machinectl login,因为我想通过非交互式脚本文件执行这么多命令)。 谁能告诉我获取它的简单方法?

【问题讨论】:

    标签: linux virtualization systemd


    【解决方案1】:

    您需要使用--remain-after-exit 告诉 Systemd 保留服务单元,以便获取其状态。

    # systemd-run  --unit=kek$RANDOM --remain-after-exit     bash -c 'sleep 2; id; exit 216'
    Running as unit kek30537.service.
    
    # systemctl show  kek30537.service  -p ExecMainStatus
    ExecMainStatus=216
    

    【讨论】:

      【解决方案2】:

      systemd-run 的结果状态码好像总是0 除非调用运行时 systemd 单元失败。

      是的,这是正确且预期的行为。在这种特殊情况下,systemd-run 不会自行运行命令。它使用您选择的参数创建、验证和排队一个临时的 .service 文件,然后由“--system”或“--user”服务管理器启动。 得到你想要的.. TL;DR

      # systemd-run --scope /bin/true
      # echo $?
      0
      # systemd-run --scope /bin/false
      # echo $?
      1
      

      请注意,在这种情况下,作用域单元将继承调用脚本的环境,并且仅在命令完成时才返回执行..

      【讨论】:

      • 谢谢!在正常systemd-run --scope 的情况下它工作得很好,但在systemd-run --scope --machine=my_container 的情况下不起作用。错误消息是Scope execution is not supported on non-local systems.
      • @takaomag 不幸的是你运气不好......这个特殊的功能是故意没有实现的......
      • @CristianRodriguez 知道为什么systemd-run --scope --slice=test sleep 5 会出现在system.slice 而不是test.slice 吗?
      • @AlexBrand 没有适当的验证来检查切片是否存在,也没有创建新的切片。我不确定它是文档错误..(缺少“切片必须存在”)还是错误“systemd-run 也应该创建瞬态切片”
      • @CristianRodriguez 我用现有的活动切片对此进行了测试,但它仍然无法正常工作。对你起作用吗?我创建了github.com/systemd/systemd/issues/2991
      【解决方案3】:

      我不知道基于systemd 的虚拟化的细节,但是如果您需要先前命令的返回码来决定是否运行进一步的命令,或者决定运行哪些进一步的命令,一个简单的解决方案可能会是将您的命令(sudo systemd-run为前缀)所有返回代码查询并根据决策逻辑放入脚本中。

      然后只需使用sudo systemd-run /path/to/that/script 调用该脚本。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2020-02-24
        • 2015-04-22
        • 1970-01-01
        • 1970-01-01
        • 2012-05-30
        • 2015-01-18
        • 2011-10-05
        相关资源
        最近更新 更多