2012-10-02 48 views
1

在以Linux为操作系统的嵌入式系统上,我想调用第三方二进制文件从数据库检索数据并将此数据附加到现有文件。 其移交给system()函数的命令字符串看起来像:linux系统c引用

"export_from_db >> /tmp/myFile" 

不幸的是,这是行不通的。 /tmp/myFile永远不会被创建!如果我省略重定向,那么数据库导出将打印到stdout。

我想知道system()和通过“>>”重定向很好地结合在一起吗?在提示我成功测试了这个命令"export_fom_db >> /tmp/myFile"!有人知道如何使用system()来实现它吗?是否需要某种引用?

回答

1

hm ..实际上,对我来说这似乎是正确的..这正是system()的用途 - 在当前shell下执行一行。那嵌入式linux的shell支持>>运算符吗?您是否在终端中手动尝试过它?

另一个想法是,你的应用程序可以在其他一些用户帐户和帐户可能运行有一些奇怪的配置,像有一些csh或ksh的,而不是猛砸(或反之亦然,这取决于你喜欢什么)。检查用户实际拥有该进程,并检查shell设置的/ etc/passwd。

此外,还有小的可能性,用户帐户,该应用程序下运行根本没有权利写到/ tmp :)一定要检查过

而且...有小的可能性,在你的'嵌入式linux'上只是简单地实现了system(),它只是用给定的参数调用应用程序,并跳过所有其他shell-wise操作符。这可能是为了节省资源,因为system()虽然很少被使用,或者只是被你的linux设计者“过于沉重”,它依赖于发行版。如果你告诉我们哪一个那么,如果情况确实如此,那么拥有更多知识的人们可能会说。

1

在嵌入式系统上,您最好自己实施system()。考虑下面的代码(未经测试!):

#include <unistd.h> 
#include <stdlib.h> 
#include <sys/types.h> 
#include <sys/wait.h> 
#include <errno.h> 

/* Helper function: Open the specified file at the desired descriptor. 
*/ 
static int openfd(const int descriptor, 
        const char *const filename, 
        const int flags, const mode_t mode) 
{ 
    int fd, result; 

    if (!filename || descriptor == -1) 
     return errno = EINVAL; 

    /* Close existing descriptor. Ignore errors. Hopefully it is reused. */ 
    do { 
     result = close(descriptor); 
    } while (result == -1 && errno == EINTR); 

    /* Open the desired file. */ 
    do { 
     fd = open(filename, flags, mode); 
    } while (fd == -1 && errno == EINTR); 
    if (fd == -1) 
     return errno; 

    /* Did we get lucky, and get the correct descriptor already? */ 
    if (fd == descriptor) 
     return 0; 

    /* Move the descriptor. */ 
    do { 
     result = dup2(fd, descriptor); 
    } while (result == -1 && errno == EINTR); 
    if (result == -1) { 
     const int saved_errno = errno; 
     do { 
      result = close(fd); 
     } while (result == -1 && errno == EINTR); 
     return errno = saved_errno; 
    } 

    /* Close the temporary descriptor. */ 
    do { 
     result = close(fd); 
    } while (result == -1 && errno == EINTR); 
    if (result == -1) { 
     const int saved_errno = errno; 
     do { 
      result = close(descriptor); 
     } while (result == -1 && errno == EINTR); 
     return errno = saved_errno; 
    } 

    return 0; 
} 

/* Start command on the background. 
* Note: args[1] is the first argument, args[0] is the command name. 
* NULL input/output/error redirects from/to /dev/null. 
* Empty string for input/output/error does no redirections; 
* the command the uses the same input/output/error. 
* For non-empty output or error, specify the 'man 2 open' O_ flags too. 
* 
* Returns (pid_t)0 with errno set if an error occurs, 
* otherwise the PID of the child process started. 
*/ 
pid_t run(const char *file, 
      char *const args[], 
      const char *const input, 
      const char *const output, const int output_flags, 
      const char *const error, const int error_flags) 
{ 
    pid_t child; 
    int result, flags; 

    if (!cmd || !arg || !arg[0]) { 
     errno = EINVAL; 
     return (pid_t)0; 
    } 

    child = fork(); 
    if (child == (pid_t)-1) 
     return (pid_t)0; 

    if (child) 
     return child; 

    /* This is the child process. */ 
    if (input && *input) 
     result = openfd(STDIN_FILENO, input, O_RDONLY | O_NOCTTY, 0); 
    else 
    if (!input) 
     result = openfd(STDIN_FILENO, "/dev/null", O_RDONLY | O_NOCTTY, 0); 
    else 
     result = 0; 
    if (result) 
     exit(127); 

    if (output && *output) 
     result = openfd(STDOUT_FILENO, output, output_flags, 0666); 
    else 
    if (!output) 
     result = openfd(STDOUT_FILENO, "/dev/null", O_WRONLY | O_NOCTTY, 0); 
    else 
     result = 0; 
    if (result) 
     exit(127); 

    if (error && *error) 
     result = openfd(STDERR_FILENO, error, error_flags, 0666); 
    else 
    if (!error) 
     result = openfd(STDERR_FILENO, "/dev/null", O_WRONLY | O_NOCTTY, 0); 
    else 
     result = 0; 
    if (result) 
     exit(127); 

    execvp(file, args); 

    exit(127); 
} 

run()只启动命令,你需要等待它完成。请注意,您的主程序可以同时进行有意义的工作,除非它需要立即退出状态(或命令应创建的文件)。使用示例:

/* Command to run. NULL terminates the list. */ 
char *const cmd[] = { "ls", "-l", NULL }; 

pid_t child, p; 
int status; 

child = run(cmd[0], cmd, 
      NULL /* < /dev/null */, 
      "/tmp/some-log-file", O_WRONLY | O_CREAT | O_APPEND, 
      "", 0 /* No redirection for standard error */); 
if (!child) { 
    fprintf(stderr, "Cannot run '%s': %s.\n", cmd[0], strerror(errno)); 
    exit(1); 
} 

do { 
    status = 0; 
    p = waitpid(child, &status, 0); 
} while (p == (pid_t)-1 && errno == EINTR); 
if (p == (pid_t)-1) { 
    fprintf(stderr, "Lost '%s': %s.\n", cmd[0], strerror(errno)); 
    exit(1); 
} 

if (WIFEXITED(status)) { 
    if (!WEXITSTATUS(status)) 
     printf("Command executed successfully.\n"); 
    else 
     printf("Command failed with exit status %d.\n", WEXITSTATUS(status)); 
} else 
if (WSIGNALED(status)) 
    printf("Command died from signal %s.\n", strsignal(WTERMSIG(status))); 
else 
    printf("Command died unexpectedly.\n"); 

虽然最后部分通常缩写为

if (WIFEXITED(status) && !WEXITSTATUS(status)) 
    printf("'%s': Successful.\n", cmd[0]); 
else 
    printf("'%s': Failed.\n", cmd[0]); 

请注意,如果你无论如何处理输出,你应该使用的管道(或者popen()或以上的扩展版本功能)。

希望你觉得这个有用。