我有一个shell脚本,它将执行以下操作:
file:example.sh
#!/bin/sh
#some other code
echo "someconfig">config_file
我希望config_file仅包含someconfig,但是config_file发生了奇怪的事情,它在第一行中有一个'c'。我在执行example.sh
的父进程中没有找到printf('c')我的进程将以这种方式调用linux c函数来执行脚本:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/wait.h>
#include <sys/types.h>
int execute_shell(const char *shell)
{
pid_t pid;
int iRet = 0;
if((pid = fork()) < 0)
{
return -1;
}
else if (pid == 0)
{
execlp("sh", "sh", "-c", shell, (char*)0);
exit(127);
}
else
{
while (waitpid(pid, &iRet, 0) < 0) {
if (errno != EINTR) {
iRet = -1;
break;
}
}
}
if(WIFEXITED(iRet) == 0)
{
return -1;
}
if(WEXITSTATUS(iRet) != 0)
{
return -1;
}
return 0;
}
int main()
{
char shell_cmd[1024]="./example.sh";
if( execute_shell(shell_cmd) == -1 )
{
// handle error
}
/*other code blew,may be will write to stdout*/
return 0;
}
有时配置文件看起来很奇怪,而不是shell脚本回显的内容。
我使用cmd分析可能性: strace -f ./fork
[pid 12235] open("config_file", O_WRONLY|O_CREAT|O_TRUNC, 0666) = 3
[pid 12235] fcntl(1, F_GETFD) = 0
[pid 12235] fcntl(1, F_DUPFD, 10) = 10
[pid 12235] fcntl(1, F_GETFD) = 0
[pid 12235] fcntl(10, F_SETFD, FD_CLOEXEC) = 0
[pid 12235] dup2(3, 1) = 1
[pid 12235] close(3) = 0
[pid 12235] fstat(1, {st_mode=S_IFREG|0644, st_size=0, ...}) = 0
[pid 12235] mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fbabb409000
[pid 12235] write(1, "someconfig\n", 11) = 11
[pid 12235] dup2(10, 1) = 1
[pid 12235] fcntl(10, F_GETFD) = 0x1 (flags FD_CLOEXEC)
[pid 12235] close(10) = 0
[pid 12235] rt_sigprocmask(SIG_BLOCK, NULL, [], 8) = 0
[pid 12235] read(255, "", 52) = 0
[pid 12235] exit_group(0) = ?
[pid 12235] +++ exited with 0 +++
<... wait4 resumed> [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], 0, NULL) = 12235
我不明白函数= num的含义是什么? 如果有人分析strace输出的含义,我将不胜感激。
我怀疑父母和孩子都向标准输出写入内容,导致config中出现奇怪的输出。
在我的项目中,我们仅使用linux c代码执行一个shell脚本,它将回显someconfig到config_file,它通常运行6个月,但有一天该配置看起来很奇怪(两台机器,具有相同的错误,第一行与c而不是它的回声)。
我只是想谈谈是否有发生这种情况的可能性,以指导解决该问题。
分析strace输出后,子进程执行一些fd操作,请确保子进程和父进程回显到不同的fd。所以我认为没有可能使配置混乱。
答案 0 :(得分:1)
以下建议的代码:
execlp()
这是我修复的问题:
waitpid()
时返回错误。<sys/types.h>
和<sys/wait.h>
:waitpid()
_exit()
替换了对exit()
的所有调用,因为大多数新手程序员都不知道使用_exit()
而不是exit()
的结果execute_shell()
现在,建议的代码:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <errno.h>
int execute_shell(const char *shell)
{
pid_t pid;
pid = fork();
if( pid < 0 )
{
perror( "fork failed" );
return -1;
}
else if (pid == 0)
{ // child process
execlp("sh", "sh", "-c", shell, (char*)0);
perror( "execlp failed" );
return -2;
}
else
{ // parent process
int iRet;
if( waitpid(pid, &iRet, 0) == -1 )
{
return -3;
}
if (errno != EINTR)
{
return -4;
}
if(WIFEXITED(iRet) == 0)
{
return -5;
}
if(WEXITSTATUS(iRet) != 0)
{
return -6;
}
}
return 0;
}
int main( void )
{
char shell_cmd[1024]="./example.sh";
if( execute_shell(shell_cmd) )
{
// handle error
}
/*other code blew,may be will write to stdout*/
return 0;
}
我创建了一个文件:example.sh
,其中包含:
#!/bin/sh
#some other code
echo "someconfig" > config_file
然后运行命令:
chmod 777 example.sh
使其可执行,然后运行我发布的程序。
结果没有显示在终端上,但是,现在有了一个新文件:config_file
,其中包含:
someconfig
我运行了几次发布的代码,文件config_file
的内容没有改变
I.E。没有流浪字符“ c” s 你还没告诉我们什么?