2012-10-02 85 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()或以上的擴展版本功能)。

希望你覺得這個有用。