【问题标题】:linux execute shell script which echo something to a file [closed]linux执行shell脚本,将某些内容回显到文件[关闭]
【发布时间】:2019-07-04 17:00:08
【问题描述】:

我有一个 shell 脚本,它将执行如下所示的内容:

文件: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

我不明白function = num是什么意思? 如果有人分析 strace 输出的含义,我将不胜感激。

我怀疑父母和孩子写入标准输出,导致配置中的奇怪输出。

在我的项目中,我们只是使用 linux c 代码执行一个 shell 脚本,它会将 someconfig 回显到 config_file,它正常运行 6 个月,但是有一天配置看起来很奇怪(两台机器,同样的错误,第一行用 c不是它的回声)。

我只是想谈谈是否有可能发生这种情况,以便找到解决问题的方向。

分析strace输出后,子进程执行一些fd操作,确保子进程和父进程回显到不同的fd。所以我认为没有可能使配置混乱。

【问题讨论】:

  • 查看man 工具以获取有关strace 等工具的更多信息:man strace。它说“跟踪中的每一行都包含系统调用名称,后面是括号中的参数及其返回值。”并举个例子
  • 你能用问题中的最少代码重现问题吗?或者只有在#some other code/*other code blew,may be will write to stdout*/处添加一些东西?
  • 如果execlp 成功,它永远不会返回,所以你的else { _exit(0); } 是多余的。
  • 函数:waitpid() 需要以下语句:#include &lt;sys/types.h&gt;#include &lt;sys/wait.h&gt; 编译时,始终启用警告,然后修复这些警告。 (对于gcc,至少使用:-Wall -Wextra -Wconversion -pedantic -std=gnu11)注意:其他编译器使用不同的选项来产生相同的输出
  • @user3629249 成功则不返回。 if 是多余的但不是无效的

标签: c linux shell fork


【解决方案1】:

以下建议的代码:

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

这是我修复的:

  1. execlp() 的调用(和结果)
  2. fork() 调用失败时的处理
  3. 在返回错误时调用waitpid()
  4. 为函数添加了包含语句:&lt;sys/types.h&gt;&lt;sys/wait.h&gt;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 你没有告诉我们什么?

【讨论】:

  • 你能把它放在你的答案中吗?
  • 我已经发布了shell脚本,它主要将配置信息回显到配置文件,感谢您的建议。我按照您的建议修改了代码,其他评论自爆。如果有任何问题,请告诉我.
  • 在我的项目中,我们只是使用 linux c 代码执行一个 shell 脚本,它会将 someconfig 回显到 config_file,它正常运行 6 个月,但有一天配置看起来很奇怪(两台机器,同样的错误,第一行c),我只是想谈谈是否有可能发生这种情况,以便有一个解决问题的方向。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-02-04
  • 2013-05-08
  • 1970-01-01
  • 1970-01-01
  • 2014-03-26
  • 2015-04-22
  • 1970-01-01
相关资源
最近更新 更多