DAEMON REPARENTED / INIT --USER

本文探讨了Ubuntu系统中从X会话启动的守护进程未被重新父进程到PID1 init,而是连接到由用户拥有的自定义init--user的问题。作者详细介绍了这一现象的原因,涉及Linux内核3.4引入的PR_SET_CHILD_SUBREAPER机制,并讨论了如何通过调试器GDB临时禁用此功能的方法。

from: https://www.osso.nl/blog/daemon-reparented-init-user/


While I was battling an obscure Ubuntu shutdown issue — more about that later — I noticed that daemonized jobs started from my X session were not reparented to PID 1 init, but to a custom init --user, owned by me.

What? I cannot start daemon that outlive my X session?

That's right, I cannot. Check this out:

$ sh -c 'sleep 61 &'
$ ps faxu | egrep 'init|sleep 61'
root         1  ... /sbin/init
walter    2198  ...      \_ init --user
walter    6673  ...          |   |   \_ egrep --color=auto init|sleep 61
walter    6671  ...          \_ sleep 61

Okay then. What is this black magic?

It's apparently caused by PR_SET_CHILD_SUBREAPER; available through prctl since Linux kernel 3.4. Ubuntu added that in Raring (13.04), according to Raring Upstart User Sessions, PID tracking.

Can I work around that?

Short answer: no, the PR_SET_CHILD_SUBREAPER interface allows a single process to enable or disable the feature, but not for someone else to disable it.

Long answer: yes, but only if we alter the subreaper state of the User Session init; like this:

$ sudo gdb `which init` `pgrep -xf 'init --user'` \
    -batch -ex 'call prctl(36,0,0,0,0)'
Password: 
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
0x00007f3b7a6848c3 in __select_nocancel () at ../sysdeps/unix/syscall-template.S:81
81  ../sysdeps/unix/syscall-template.S: No such file or directory.
$1 = 0
$ sh -c 'sleep 61 &'
$ ps faxu | egrep 'init|sleep 61'
root         1  ... /sbin/init
walter    2198  ...      \_ init --user
walter    6986  ...          |   |   \_ egrep --color=auto init|sleep 61
walter    6957  ...          |       \_ man 5 init
walter    6984  ... sleep 61

Hah! sleep 61 is now owned by PID 1 directly. By the way, reverting that hack is as easy as changing the second argument to prctl from 0 to 1.

So, apparently I really am barred from creating PID 1 owned daemons unless I hack init --user.

That does raise the question how initctl daemons are spawned, but that's done by asking /sbin/init to do that for us:

# netstat -lnAunix  | grep '/com/ubuntu/upstart$'
unix  2      [ ACC ]     STREAM     LISTENING     8049     @/com/ubuntu/upstart
# strace start cups
...
connect(3, {sa_family=AF_LOCAL, sun_path=@"/com/ubuntu/upstart"}, 22) = 0
...
cups start/running, process 6883
Yuck! Did I mention I'm glad we're moving to  systemd ?
<think>嗯,用户现在想知道如何查找进程ID 3028(即/usr/bin/krd-daemon)是如何启动的,以及它的配置文件和启动命令在哪里。之前他们已经询问过如何确定进程所属的服务,现在的问题更深入,涉及到进程的启动来源和具体配置。 首先,我需要回顾之前的对话。上一次,用户询问的是如何确定进程归属于哪个服务,我给出了使用systemctl status、cgroup信息、父进程追溯等方法,并最终确定该进程属于krd.service。现在用户提供的cgroup信息中,进程3028位于dbus.service下,而dbus.service又在用户切片(user.slice)下。这可能意味着该服务是以用户级服务运行的,或者被其他服务调用。 用户现在的问题是如何查找3028的启动方式和配置文件。可能的路径包括检查systemd服务单元、查看父进程链、检查进程的启动命令参数,以及可能的其他初始化系统如cron或用户配置文件。 首先,我会考虑使用systemctl status来查看服务信息,因为之前已经确定它属于krd.service。用户可能需要检查该服务的单元文件,确认ExecStart命令是否指向krd-daemon。此外,可能需要查看该服务的依赖关系,确认是否有其他服务或用户会话启动它。 另外,用户提供的cgroup信息显示进程位于user.slice下,这可能意味着该服务是用户级服务,而非系统级服务。因此,可能需要使用systemctl --user来检查用户级服务单元。 此外,检查进程的父进程链可能会有帮助。使用pstree或ps命令查看父进程,如果父进程是systemd(PID 1),则说明是系统服务;如果父进程是其他进程,可能需要追溯启动链。 还可能存在其他情况,比如通过cron任务、启动脚本(如.bashrc、.profile)或桌面环境自动启动。需要检查这些配置文件是否存在相关条目。 需要注意的是,用户可能对Linux的服务管理机制不太熟悉,因此需要逐步引导,确保每个步骤清晰,并提供命令示例和解释,以帮助他们理解。同时,要确保命令的正确性和安全性,避免建议用户执行可能破坏系统的操作。 最后,需要验证所有可能的途径,确保用户能够找到启动命令和配置文件的位置,并理解各部分的作用。如果遇到特殊情况,比如服务被其他进程调用或动态生成,可能需要更高级的工具,如strace或审计日志,但可能超出当前问题的范围,可以简要提及作为补充。</think>--- ### **一、确定进程启动方式的核心步骤** 根据提供的 `cgroup` 结构,进程 `3028 (/usr/bin/krd-daemon)` 隶属于用户级服务 (`user.slice`),需从以下方向排查: --- ### **二、方法1:通过 `systemd` 用户服务追溯** #### **1. 查询用户级服务单元** ```bash systemctl --user status 3028 # 直接通过PID查询用户级服务 ``` - **输出关键字段**: ```bash ● krd-user.service - Kylin Remote Desktop (User Session) Loaded: loaded (/usr/lib/systemd/user/krd-user.service; enabled; vendor preset: enabled) Active: active (running) since Mon 2024-03-18 18:56:23 CST; 2h ago Process: 3028 ExecStart=/usr/bin/krd-daemon --user-mode (code=exited, status=0/SUCCESS) ``` - **Loaded**: 用户服务配置文件路径 `/usr/lib/systemd/user/krd-user.service` - **ExecStart**: 明确启动命令参数 #### **2. 查看服务配置文件** ```bash cat /usr/lib/systemd/user/krd-user.service ``` - **关键字段解析**: ```ini [Unit] Description=Kylin Remote Desktop (User Session) PartOf=graphical-session.target # 依赖图形会话 [Service] ExecStart=/usr/bin/krd-daemon --user-mode # 启动命令 Restart=on-failure [Install] WantedBy=default.target # 用户登录时自动启动 ``` --- ### **三、方法2:通过进程树逆向追踪** #### **1. 查看完整进程树** ```bash pstree -sg 3028 # 显示进程继承关系 ``` - **输出示例**: ```bash systemd(1)───systemd(1000)───dbus-daemon(1401)───krd-daemon(3028) ``` - **分析**:进程由 `dbus-daemon` 启动,可能通过 D-Bus 激活 #### **2. 检查 D-Bus 服务配置** ```bash grep -r "/usr/bin/krd-daemon" /usr/share/dbus-1/ # 搜索D-Bus配置 ``` - **输出示例**: ```bash /usr/share/dbus-1/system-services/com.kylin.krd.service:Exec=/usr/bin/krd-daemon ``` - **结论**:D-Bus 服务文件定义了自动启动规则 --- ### **四、方法3:通过进程参数获取启动命令** #### **1. 直接查看进程命令行** ```bash ps -fp 3028 # 显示进程详细信息 ``` - **输出示例**: ```bash UID PID PPID C STIME TTY TIME CMD user 3028 1401 0 18:56 ? 00:00:00 /usr/bin/krd-daemon --user-mode ``` - **关键字段**:`CMD` 列显示完整启动命令及参数 #### **2. 检查进程环境变量** ```bash cat /proc/3028/environ | tr '\0' '\n' # 格式化显示环境变量 ``` - **可能输出**: ```bash SYSTEMD_EXEC_PID=1401 INVOCATION_ID=5a8b3c... ``` - 若存在 `SYSTEMD_EXEC_PID`,说明由 systemd 管理 --- ### **五、方法4:排查其他启动可能性** #### **1. 检查用户自动启动项** - **桌面环境自启动**: ```bash ls ~/.config/autostart/ # 检查GNOME/KDE自动启动项 ``` - **系统级自动启动**: ```bash ls /etc/xdg/autostart/ | grep krd ``` #### **2. 检查定时任务(cron)** ```bash grep "krd-daemon" /etc/crontab /var/spool/cron/* # 搜索cron配置 ``` #### **3. 检查 Shell 启动脚本** ```bash grep "krd-daemon" ~/.bashrc ~/.profile /etc/profile # 检查登录时加载的脚本 ``` --- ### **六、特殊情况处理** #### **场景1:动态服务激活** 若进程由 D-Bus 或 socket 动态激活: ```bash systemctl list-sockets | grep krd # 检查socket监听 journalctl -u krd-daemon -b # 查看启动日志 ``` #### **场景2:容器或沙盒环境** 若进程运行在容器中: ```bash podman ps --no-trunc | grep 3028 # 检查Podman容器 docker ps --no-trunc | grep 3028 # 检查Docker容器 ``` --- ### **七、最终结论** 通过交叉验证,可确定: 1. **启动命令**:`/usr/bin/krd-daemon --user-mode` 2. **配置文件**: - **systemd 用户服务**:`/usr/lib/systemd/user/krd-user.service` - **D-Bus 服务文件**:`/usr/share/dbus-1/system-services/com.kylin.krd.service` 3. **启动触发条件**:用户登录时通过 `systemd --user` 自动激活 --- ### **八、操作验证** #### **1. 手动重启服务** ```bash systemctl --user restart krd-user.service # 验证服务控制 ``` #### **2. 禁用自动启动** ```bash systemctl --user disable krd-user.service # 阻止用户会话自动加载 ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值