简体   繁体   English

调用shell脚本后返回主C程序

[英]Return to main C program after calling shell script

I have a C program running on my Raspberry-Pi that continuously reads serial info from an AVR. 我在Raspberry-Pi上运行了一个C程序,该程序不断从AVR读取串行信息。 I want to write the history of commands received using a simple shell script: 我想写一个使用简单的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

This script works perfectly when called within terminal with the proper arguments, however, I want to execute it each time that a command is read from the serial line. 当在终端中使用适当的参数调用该脚本时,该脚本可以完美运行,但是,我希望每次从串行线路读取命令时都执行该脚本。 The C program currently reads the command & address and prints it to the standard io, so what I would like to do is call the script after this, to write data to a file. C程序当前读取命令和地址并将其打印到标准io,因此我想做的是在此之后调用脚本,以将数据写入文件。

When calling the script in my code like this: 当像这样在我的代码中调用脚本时:

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

it exits the main program. 它退出主程序。 How can I return to the main program after calling the script? 调用脚本后如何返回主程序? Or is there a way to do it when running the script as a background process? 还是在将脚本作为后台进程运行时有办法做到这一点? I'm aware that it would be much simpler to do it with standard C file i/o, but if it's possible using the shell, I'd like to do that :) 我知道使用标准C文件I / O进行操作要简单得多,但是如果可以使用Shell,我想这样做:)

Regards, Jaco 问候,哈科

The exec family of function replaces the process with the new process. exec函数家族用新进程替换了该进程。 They only return in case of an error. 它们仅在出现错误的情况下返回。

What you seem to want is the system function, which creates a shell process for you and then executes the command in the argument. 您似乎想要的是system函数,该函数为您创建一个shell进程,然后在自变量中执行命令。

By the way, you set up your argument array wrong anyway, remember that arrays indices start with zero . 顺便说一句,您反正将argument数组设置为错误,请记住数组索引从零开始 Also, the first entry in the argument array should be the program name, meaning you need to set argument[0] to program , and of course change the array size to four. 另外, argument数组中的第一个条目应为程序名称,这意味着您需要将argument[0]设置为program ,并且当然要将数组大小更改为4。


However, as trojanfoe notes, you don't really need to call a shell script at all unless there are some other special commands that needs to be run when you receive the message.If you just want to print some logging information to a file you can do it from inside the program very easily: 但是,正如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);

Put this in a separate function, that you call whenever you need. 将其放在单独的函数中,可在需要时调用。 And note that if you want to write more to the file, then you could open it at the beginning of the program and not close it until you are exiting the program. 并请注意,如果您想向文件中写入更多内容,则可以在程序开始时将其打开,直到退出该程序才将其关闭。

Calling a shell script, especially so frequently, will cripple the performance of your program, so use built-in logging functionality instead. 尤其如此频繁地调用shell脚本会削弱程序的性能,因此请使用内置的日志记录功能。 You might need to change the semantics of logData() as I don't know what form your "command" and "address" takes. 您可能需要更改logData()的语义,因为我不知道您的“命令”和“地址”采用什么形式。

logger.h: logger.h:

#pragma once

#include <stdbool.h>

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

logger.c: logger.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;
    }
}

main.c: main.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;
}

Compilation and testing: 编译和测试:

$ 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'

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM