Objective-C中system函数执行echo写入文件失败问题排查
分析与解决方案
看起来问题出在Shell语法兼容性和**$?的上下文含义**上,我们一步步拆解:
1. 核心问题:[[ ]]的Shell兼容性
iOS默认的system()函数调用的是/bin/sh(通常是POSIX标准兼容的Shell,比如Dash),而[[ ]]是Bash独有的扩展语法,sh并不支持。这会导致你的第一个if语句在执行时直接报错,根本没走到echo和文件写入的步骤。
那为什么第二个命令能正常工作?大概率是因为你的SSH会话默认使用Bash(而system()调用的是sh),手动执行时的环境和system()调用的环境不一致;或者第二个命令的[[ ]]嵌套结构在sh中恰好没有触发语法错误。
2. 次要问题:$?的上下文无效
你第一个命令里的${?}是新启动的Shell进程的初始退出状态(默认是0),而不是你Objective-C代码中某个前置操作的退出码。如果你的目的是记录某个操作的执行结果,这种写法本身逻辑就有问题——$?只能反映Shell中前一条命令的状态,而这里Shell刚启动,没有可参考的前置命令。
解决方案
方案一:改用POSIX兼容的Shell语法
把[[ ]]换成POSIX标准的[ ],同时用-eq做数值比较:
system("if [ ${?} -eq 0 ]; then echo '0' > /var/mobile/CCC/STATUS.txt; else echo '1' >> /var/mobile/CCC/STATUS.txt; fi");
方案二:指定用Bash执行命令
强制system()调用Bash来解析命令,避开sh的语法限制:
system("/bin/bash -c 'if [[ ${?} == 0 ]]; then echo \"0\" > /var/mobile/CCC/STATUS.txt; else echo \"1\" >> /var/mobile/CCC/STATUS.txt; fi'");
方案三:跳过Shell,直接在OC中处理(推荐)
用Objective-C原生的文件操作替代system(),既避免Shell兼容性问题,又能直接控制要写入的状态值,更可靠:
// 假设你要记录的是某个操作的退出码ret int ret = 0; // 替换成你的实际操作返回值 NSString *statusFile = @"/var/mobile/CCC/STATUS.txt"; NSString *statusContent = [NSString stringWithFormat:@"%d\n", ret]; NSError *error = nil; [statusContent writeToFile:statusFile atomically:YES encoding:NSUTF8StringEncoding error:&error]; if (error) { NSLog(@"写入失败: %@", error.localizedDescription); }
方案四:简化Shell命令
如果只是要把当前Shell的初始状态(或某个命令的退出码)写入文件,完全不需要if判断,直接写:
// 写入当前Shell的初始退出码(固定为0) system("echo $? > /var/mobile/CCC/STATUS.txt"); // 如果是要记录某个命令的退出码,比如执行ls后的状态: system("ls /some/path; echo $? > /var/mobile/CCC/STATUS.txt");
内容的提问来源于stack exchange,提问作者Jacob Collins
相关产品推荐
相关产品推荐

