嵌入式Linux调用execv()/execve()时进程被杀死的排查求助
这种情况我之前在老版本嵌入式Linux(3.4.x内核)上碰到过类似的,从su tstuser也直接提示Killed来看,问题大概率出在用户身份切换后的初始化环节,而不是你程序里的setuid/setgid逻辑。下面给你一步步排查的思路:
1. 先检查tstuser的登录shell配置
首先看/etc/passwd里tstuser的shell设置,执行:
cat /etc/passwd | grep tstuser
重点看最后一个字段(比如/bin/bash):
- 如果这个shell程序不存在(比如系统只装了
/bin/sh但配置成了/bin/bash),切换用户时execve会失败,可能触发Killed; - 如果是
/bin/false或/sbin/nologin,那su会直接退出,但不会提示Killed,所以更可能是前者。
临时修改shell试试:
usermod -s /bin/sh tstuser
然后再执行su tstuser,看是否正常。
2. 排查用户家目录的权限与初始化文件
如果shell没问题,就检查tstuser的家目录:
- 看权限是否正确:
ls -ld /home/tstuser
所有者必须是tstuser:tstuser,权限建议是700或755,如果权限过于开放(比如777)或者所有者不对,可能导致shell初始化时出错。
- 检查家目录下的初始化脚本(
.bashrc、.profile、.bash_profile):
这些脚本如果有错误(比如调用了不存在的命令、无限循环、或者执行了有权限问题的程序),shell启动时可能被内核终止。可以先临时重命名这些文件:
mv /home/tstuser/.bashrc /home/tstuser/.bashrc.bak mv /home/tstuser/.profile /home/tstuser/.profile.bak
再尝试su tstuser,如果正常了,就逐个恢复文件排查问题行。
3. 用strace跟踪执行过程,定位具体崩溃点
这是最直接的排查手段,能看到系统调用层面的错误:
- 跟踪su命令:
strace su tstuser
看输出的最后几步,重点关注execve调用后的系统调用,比如是否有SIGKILL信号,或者某个文件无法打开。
- 跟踪你的程序:
strace -f ./your_program
-f参数会跟踪fork出来的子进程,能看到setuid/setgid后execve的完整流程,看是哪个环节触发了终止。
4. 检查PAM配置与系统安全机制
老版本嵌入式系统的PAM配置可能有问题:
- 查看
/etc/pam.d/su或/etc/pam.d/system-auth里的配置,有没有加载错误的PAM模块(比如某些依赖库缺失的模块),可以临时注释掉非必要的session模块,再测试su。 - 检查SELinux/AppArmor状态:
虽然3.4.0内核SELinux默认可能没开启,但还是确认下:
getenforce
如果是Enforcing模式,临时改成Permissive试试:
setenforce 0
再测试切换用户。
5. 检查内核核心转储配置
如果系统允许生成core文件,能直接定位崩溃点:
- 检查核心转储是否开启:
ulimit -c
如果是0,临时开启:
ulimit -c unlimited
然后执行su tstuser,如果生成了core文件,用gdb分析:
gdb /bin/sh core
(这里假设shell是/bin/sh,换成实际的shell路径),输入bt查看调用栈,就能知道哪里崩溃了。
内容的提问来源于stack exchange,提问作者Dániel Petri

