2

我在我的 Raspberry-Pi 上运行了一个 C 程序,它不断地从 AVR 读取串行信息。我想用一个简单的 shell 脚本编写接收到的命令的历史记录:

#!/bin/bash

echo "Command $2 received from address $1" 

date_time=$(date)                       #read current date from terminal
echo " $date_time Address: $1 Cmd: $2" >> file.txt      #echo address & command to file, redirect stdio

exit 0

当在终端中使用适当的参数调用此脚本时,该脚本可以完美运行,但是,我想在每次从串行线路读取命令时执行它。C程序当前读取命令和地址并将其打印到标准io,所以我想做的是在此之后调用脚本,将数据写入文件。

在我的代码中调用脚本时,如下所示:

    char* args[3];
char* program="ioExport.sh";
    args[1]=addr;
    args[2]=cmd;
    args[3]=NULL;
    execv(program,args);

它退出主程序。调用脚本后如何返回主程序?或者在将脚本作为后台进程运行时有没有办法做到这一点?我知道使用标准 C 文件 i/o 会更简单,但如果可以使用 shell,我想这样做:)

问候, 雅科

4

2 回答 2

3

exec函数族用新进程替换进程。它们仅在出现错误时返回。

您似乎想要的是该system函数,它为您创建一个 shell 进程,然后执行参数中的命令。

顺便说一句,argument无论如何,您都错误地设置了数组,请记住数组索引以zero开头。此外,数组中的第一个条目argument应该是程序名称,这意味着您需要设置argument[0]program,当然还需要将数组大小更改为四。


但是,正如 trojanfoe 所指出的,您根本不需要调用 shell 脚本,除非在收到消息时需要运行其他一些特殊命令。如果您只想将一些日志记录信息打印到文件中,您可以可以很容易地从程序内部完成:

/* First get the date and time string */
time_t now = time(NULL);
char *timestring = ctime(&now);

/* It contains a trailing newline, remove that by */
/* overwriting the newline with the string terminator */
timestring[strlen(timestring) - 1] = '\0';

/* Open the file for appending (i.e. writing at the end) */
FILE *file = fopen("file.txt", "a");

/* And write your message to your file */
fprintf(file, "%s Address: %s Cmd: %s\n", timestring, addr, cmd);

/* Close the file */
fclose(file);

把它放在一个单独的函数中,你可以随时调用。请注意,如果您想向文件中写入更多内容,则可以在程序开始时打开它,并且在退出程序之前不要关闭它。

于 2013-09-03T12:23:50.587 回答
1

调用 shell 脚本,尤其是频繁调用,会削弱程序的性能,因此请改用内置的日志记录功能。您可能需要更改语义,logData()因为我不知道您的“命令”和“地址”采用什么形式。

记录器.h:

#pragma once

#include <stdbool.h>

extern bool logOpen(const char *filename);
extern void logData(const char *command, const char *address);
extern void logClose();

记录器.c:

#include "logger.h"
#include <stdio.h>
#include <sys/time.h>

static FILE *logfp = NULL;

bool logOpen(const char *filename) {
    logfp = fopen(filename, "w+");
    return logfp != NULL;
}

void logData(const char *command, const char *address) {
    struct timeval tv;
    struct tm tm;

    if (!logfp)
        return;

    gettimeofday(&tv, 0);
    localtime_r(&tv.tv_sec, &tm);

    fprintf(logfp, "%02d:%02d:%02d.%03u: command='%s' address='%s'\n",
        tm.tm_hour, tm.tm_min, tm.tm_sec, (unsigned)(tv.tv_usec / 1000),
        command, address);

}

void logClose() {
    if (logfp) {
        fclose(logfp);
        logfp = NULL;
    }
}

主.c:

#include "logger.h"

int main(int argc, const char **argv) {

    logOpen("file.log");

    logData("Command 1", "Address 1");
    logData("Command 2", "Address 2");
    logData("Command 3", "Address 3");
    logData("Command 4", "Address 4");

    logClose();
    return 0;
}

编译和测试:

$ clang -o test main.c logger.c
$ ./test
$ more file.log
13:40:08.399: command='Command 1' address='Address 1'
13:40:08.399: command='Command 2' address='Address 2'
13:40:08.399: command='Command 3' address='Address 3'
13:40:08.399: command='Command 4' address='Address 4'
于 2013-09-03T12:42:57.833 回答