bea*_*mit 103 shell-script init portability
这可能与检测操作系统有关,但我特别需要系统上当前使用的 init 系统。
Fedora 15 和 Ubuntu 现在使用 systemd,Ubuntu 过去使用 Upstart(很长时间默认直到 15.04),而其他人使用 System V 的变体。
我有一个应用程序,我正在编写它作为跨平台守护程序。初始化脚本是根据可以在配置时传入的参数动态生成的。
我想做的只是为他们正在使用的特定初始化系统生成脚本。这样,安装脚本可以在没有参数的情况下以 root 身份合理运行,并且守护进程可以自动“安装”。
这是我想出的:
这样做的最佳跨/平台方式是什么?
有点相关,我可以依赖 bash 来支持大多数 *nix 还是依赖于发行版/操作系统?
目标平台:
小智 65
我自己也遇到过这个问题,并决定做一些测试。我完全同意应该为每个发行版单独打包的答案,但有时会出现一些实际问题(尤其是人力)。
所以对于那些想要“自动检测”的人来说,这是我在一组有限的发行版中发现的(更多见下文):
你可以从以下方面看出暴发户:
[[ `/sbin/init --version` =~ upstart ]] && echo yes || echo no
Run Code Online (Sandbox Code Playgroud)您可以通过以下方式告诉 systemd:
[[ `systemctl` =~ -\.mount ]] && echo yes || echo no
Run Code Online (Sandbox Code Playgroud)你可以告诉 sys-v init 从:
[[ -f /etc/init.d/cron && ! -h /etc/init.d/cron ]] && echo yes
Run Code Online (Sandbox Code Playgroud)这是我使用以下命令行的实验:
if [[ `/sbin/init --version` =~ upstart ]]; then echo using upstart;
elif [[ `systemctl` =~ -\.mount ]]; then echo using systemd;
elif [[ -f /etc/init.d/cron && ! -h /etc/init.d/cron ]]; then echo using sysv-init;
else echo cannot tell; fi
Run Code Online (Sandbox Code Playgroud)
在 ec2 实例上(我包括了 us-east AMI id):
需要明确的是:我并不是说这是万无一失的!,几乎可以肯定不是。另请注意,为方便起见,我使用 bash regexp 匹配项,但并非随处可用。以上对我现在来说已经足够了。但是,如果您发现某个发行版出现故障,请告诉我,如果有一个 EC2 AMI 重现了该问题,我会尝试修复它...
roz*_*acz 33
对于第二个问题,答案是否定的,您应该查看可移植 shell 编程的参考资料。
至于第一部分——首先,你当然要小心。我会说执行几次测试以确保- 因为有人确实安装了systemd(例如)这一事实并不意味着它实际上用作默认init. 此外,查看/proc/1/comm可能会产生误导,因为各种 init 程序的某些安装可以自动创建/sbin/init符号链接硬链接,甚至是主程序的重命名版本。
也许最有用的事情可能是查看 init 脚本类型 - 因为这些是您实际要创建的内容,无论它们运行的是什么。
作为旁注,您可能还会查看OpenRC,它旨在提供与 Linux 和 BSD 系统兼容的初始化脚本结构。
slm*_*slm 20
查看ps可以检测systemd&的各种版本的几个命令的输出,可以upstart像这样制作:
暴发户
$ ps -eaf|grep '[u]pstart'
root 492 1 0 Jan02 ? 00:00:00 upstart-udev-bridge --daemon
root 1027 1 0 Jan02 ? 00:00:00 upstart-socket-bridge --daemon
Run Code Online (Sandbox Code Playgroud)
系统
$ ps -eaf|grep '[s]ystemd'
root 1 0 0 07:27 ? 00:00:03 /usr/lib/systemd/systemd --switched-root --system --deserialize 20
root 343 1 0 07:28 ? 00:00:03 /usr/lib/systemd/systemd-journald
root 367 1 0 07:28 ? 00:00:00 /usr/lib/systemd/systemd-udevd
root 607 1 0 07:28 ? 00:00:00 /usr/lib/systemd/systemd-logind
dbus 615 1 0 07:28 ? 00:00:13 /bin/dbus-daemon --system --address=systemd: --nofork --nopidfile --systemd-activation
Run Code Online (Sandbox Code Playgroud)
注意 PID #1 的进程的名称也可能揭示正在使用哪个 init 系统。在 Fedora 19 上(使用systemd,例如:
UID PID PPID C STIME TTY TIME CMD
root 1 0 0 07:27 ? 00:00:03 /usr/lib/systemd/systemd --switched-root --system --deserialize 20
Run Code Online (Sandbox Code Playgroud)
注意它不是init。在带有 Upstart 的 Ubuntu 上,它仍然是/sbin/init.
$ ps -efa|grep init
root 1 0 0 Jan02 ? 00:00:03 /sbin/init
Run Code Online (Sandbox Code Playgroud)
注意:但请谨慎使用。没有一成不变的任何一套,说在给定的发行版中使用特定的init系统已经拥有systemd的PID#1。
通用的
$ (ps -eo "ppid,args" 2>/dev/null || echo "ps call error") \
| awk 'NR==1 || $1==1' | less
PPID COMMAND
1 /lib/systemd/systemd-journald
1 /lib/systemd/systemd-udevd
1 /lib/systemd/systemd-timesyncd
Run Code Online (Sandbox Code Playgroud)
查看 ppid 为 1 的进程(init 进程的子进程)。(一些)子进程名称可能指向正在使用的 init 系统。
如果您询问init可执行文件,您也可以从中获取一些信息。简单地解析--version输出。例如:
暴发户
$ sudo /sbin/init --version
init (upstart 1.5)
Copyright (C) 2012 Scott James Remnant, Canonical Ltd.
This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE.
Run Code Online (Sandbox Code Playgroud)
系统
$ type init
init is /usr/sbin/init
Run Code Online (Sandbox Code Playgroud)
注意:init不在其标准位置的事实有点暗示/告诉。它始终位于/sbin/initsysvinit 系统中。
sysvinit
$ type init
init is /sbin/init
Run Code Online (Sandbox Code Playgroud)
还有这个:
$ sudo init --version
init: invalid option -- -
Usage: init 0123456SsQqAaBbCcUu
Run Code Online (Sandbox Code Playgroud)
因此,似乎没有任何一种方法可以做到这一点,但是您可以制定一套检查方法,以相当高的信心确定您正在使用的初始化系统。
Mar*_* An 15
效率不高,但我似乎有效。
strings /sbin/init | grep -q "/lib/systemd" && echo SYSTEMD
strings /sbin/init | grep -q "sysvinit" && echo SYSVINIT
strings /sbin/init | grep -q "upstart" && echo UPSTART
Run Code Online (Sandbox Code Playgroud)
如果多个字符串匹配,它将打印更多行,这可以翻译为“无法猜测”。grep 中使用的字符串可以稍作修改,但在以下操作系统中进行测试时,我总是得到一行。
相同解决方案的更简单方法(但在第一场比赛时停止)
strings /sbin/init |
awk 'match($0, /(upstart|systemd|sysvinit)/) { print toupper(substr($0, RSTART, RLENGTH));exit; }'
Run Code Online (Sandbox Code Playgroud)
Ski*_*rou 12
有时它就像使用一样简单ls :
$ ls -l /sbin/init
lrwxrwxrwx 1 root root 20 juin 25 12:04 /sbin/init -> /lib/systemd/systemd
Run Code Online (Sandbox Code Playgroud)
我想如果/sbin/init不是符号链接,您将不得不进一步检查其他答案中的以下建议。
我也遇到了同样的问题,在一些 RedHat/CentOS/Debian/Ubuntu/Mint 机器上做了很多测试。这就是我最终得到的结果,结果很好。
查找 PID 为 1 的可执行文件的名称:
ps -p 1
Run Code Online (Sandbox Code Playgroud)
如果是 systemd 或 Upstart,问题就解决了。如果它是“init”,则它可能是符号链接或其他名称而不是前期名称。前进。
找到可执行文件的真实路径(仅以 root 身份工作):
ls -l `which init`
Run Code Online (Sandbox Code Playgroud)
如果init是 Upstart 或 systemd 的符号链接,则问题已解决。否则,几乎可以肯定您有 SysV init。但它可能是一个错误命名的可执行文件。前进。
找到提供可执行文件的包。不幸的是,这取决于发行版:
dpkg-query -S (executable real path) # Debian
rpm -qf (executable real path) # RedHat
Run Code Online (Sandbox Code Playgroud)然后,如果你想编写脚本(最有趣的部分,恕我直言),这些是我的单行程序(以 root 身份运行):
ls -l $(which $(ps -p 1 o comm)) | awk '{ system("dpkg-query -S "$NF) }' # Debian
ls -l $(which $(ps -p 1 o comm)) | awk '{ system("rpm -qf "$NF) }' # RedHat
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
53564 次 |
| 最近记录: |