linux执行将脚本回显到文件的shell脚本

时间:2019-07-04 17:00:08

标签: c linux shell fork

我有一个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。所以我认为没有可能使配置混乱。

1 个答案:

答案 0 :(得分:1)

以下建议的代码:

  1. 干净地编译
  2. 执行所需的功能
  3. 正确处理子功能中出现的所有故障
  4. 正确调用函数:execlp()

这是我修复的问题:

  1. execlp()的调用(和结果)
  2. fork()失败时的调用处理
  3. 调用waitpid()时返回错误。
  4. 为以下功能添加了包含语句:<sys/types.h><sys/wait.h>waitpid()
  5. _exit()替换了对exit()的所有调用,因为大多数新手程序员都不知道使用_exit()而不是exit()的结果
  6. 添加了处理从以下位置返回的值的位置: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 你还没告诉我们什么?