C程序通过system调用带sudo权限的Expect脚本开机启动异常排查
看起来你遇到的问题核心是rc.local环境与交互式root shell的环境差异——虽然都是root身份,但开机启动时的工作目录、环境变量、tty状态都和手动登录时不一样,这才导致调用Expect的system命令异常。下面是一步步的排查和解决方法:
去掉不必要的sudo:rc.local本身就是以root权限执行的,你在system调用里加
sudo反而可能触发非交互式环境下的sudo限制(比如需要tty验证、环境变量不匹配)。直接调用绝对路径的Expect即可:ret = system("/usr/bin/expect /full/path/to/expTest.exp ... arguments ...");使用脚本的绝对路径:
./expTest.exp是相对路径,rc.local的默认工作目录是/,它会在根目录找这个脚本,自然找不到。一定要替换成脚本的完整绝对路径,比如/home/marco/scripts/expTest.exp。捕获错误日志:看不到错误信息是排查的最大障碍,把system的输出重定向到日志文件,开机后就能查看具体失败原因:
ret = system("/usr/bin/expect /full/path/to/expTest.exp ... arguments ... > /var/log/exp_start.log 2>&1");开机后查看
/var/log/exp_start.log,里面会有Expect启动失败的具体提示(比如找不到依赖、参数错误、权限问题等)。检查C程序的工作目录:如果你的C程序启动时没有切换到脚本所在目录,即使脚本用了绝对路径,脚本里的相对路径命令也可能出问题。可以在调用system前先切换目录:
chdir("/full/path/to/script_directory"); ret = system("/usr/bin/expect ./expTest.exp ... arguments ...");手动测试rc.local:不用反复重启,直接手动运行rc.local脚本测试:
sudo /etc/rc.local start这样能快速验证修改是否有效,同时可以在终端看到实时输出(如果没有重定向的话)。
确保rc.local配置正确:有些系统的rc.local需要在开头加上
#!/bin/bash,并且要确保最后一行是exit 0,你的C程序启动命令要放在exit 0之前。另外,部分systemd系统默认禁用了rc.local,需要先创建对应的service文件启用它。
通过以上步骤,你应该能定位到具体的失败原因并解决问题。
内容的提问来源于stack exchange,提问作者Marco Solano

