作为Unix系统管理员,我们通过交互运行脚本来与其他人(例如DBA)启动/停止服务时遇到问题。这意味着systemd不了解服务状态。为了防止这种情况,我在这样的脚本中插入一个条件语句:
# The systemd unit creates a ORACLE_SYSTEMD_UNIT environment variable. If this
# isn't set (i.e. Not running through systemd) then abort.
if [ "${ORACLE_SYSTEMD_UNIT:+set}" == "" ]; then
logmsg "Not initiated through systemd. Aborting"
exit 2
fi
有人可以建议更干净的方法,或者是由systemd单元激活自动设置的Environment变量吗?
如注释中所指出,您可以检查父进程的命令名称。在bash中,父进程的进程ID存储在$PPID
中。给定pid的命令名称可以通过ps
获得。仅当您的脚本在systemd
下运行直接时,此方法才有效。
if [ "$(ps -o comm= $PPID)" != systemd ]; then echo "Not running under systemd" fi
如果您还想检查父母的父母等等,请重复/递归。任何pid的父对象也可以通过
ps
获得。
runsUnderSystemd() { pid="${1-$$}" [ "$pid" = 0 ] && return 1 [ "$(ps -o comm= "$pid")" = systemd ] || runsUnderSystemd "$(ps -o ppid= "$pid" | tr -d ' ')" } if ! runsUnderSystemd; then echo "Not running under systemd" fi
使用
pstree
,可以缩短为
if ! pstree -s $PPID | grep -Fwq systemd; then echo "Not running under systemd" fi
或者,您可以在
.service
文件中为systemd设置环境变量...
[Service] Environment="STARTED_BY_SYSTEMD=yes"
...然后可以在已启动服务的所有子级中检查
if [ "$STARTED_BY_SYSTEMD" != yes ]; then echo "Not running under systemd" fi
请注意,这两种方法都只是防止错误的保障。攻击者可以通过两种方式伪造或隐藏systemd。