1

OS として Linux を使用する組み込みシステムでは、サードパーティのバイナリを呼び出して、データベースからデータを取得し、このデータを既存のファイルに追加したいと考えています。system() 関数に渡されるコマンド文字列は次のようになります。

"export_from_db >> /tmp/myFile"

残念ながら、これは機能しません。/tmp/myFile作成されることはありません!リダイレクトを省略した場合、データベース エクスポートは stdout に出力されます。

system() と ">>" によるリダイレクトはうまくいくのだろうか?プロンプトで、このコマンドのテストに成功しました"export_fom_db >> /tmp/myFile"! system() を使用してそれを達成する方法を知っている人はいますか? 何らかの引用が必要ですか?

4

2 に答える 2

1

hm ..実際、私にとっては問題ないようです..これは、system()が現在のシェルで行を実行するためのものです。その組み込みLinuxのシェルは>>演算子をサポートしていますか?ターミナルで手動で試しましたか?

別の考えは、アプリケーションが他のユーザーアカウントで実行されている可能性があり、そのアカウントbashの代わりにcshまたはksh(またはその逆)を持つなど、奇妙な構成になっている可能性があるということです。どのユーザーが実際にプロセスを所有しているかを確認し、/ etc/passwdでシェルの設定を確認してください。

また、アプリが実行されているユーザーアカウントに/tmpに書き込む権限がない可能性もわずかにあります:)必ず確認してください

また...あなたの「組み込みLinux」では、system()が単純な方法で実装されている可能性がわずかにあります。これは、指定されたパラメーターを使用してアプリケーションを呼び出し、他のすべてのシェル単位の演算子をスキップします。これは、system()がめったに使用されない場合や、Linuxデザイナーによって「重すぎる」場合があるため、リソースを節約するために行われた可能性があります。ディストリビューションによって異なります。どちらかを教えてください。そうすれば、より多くの知識を持っている人はおそらくこれが事実であるかどうかを言うことができるでしょう。

于 2012-10-02T22:35:59.433 に答える
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()代わりにパイプ (または上記の関数の拡張バージョン) を使用する必要があることに注意してください。

これが役に立つことを願っています。

于 2012-10-03T00:19:17.110 に答える