C程序与Shell脚本混合编程

对于嵌入式软件开发,有时候需要在使用C语言进行开发的同时,嵌入shell脚本指令,以完成一些特定的任务。

本文结合上一篇博文“初探makefile”的程序代码,加上一个简单的shell脚本,说明两者混合编程的方法。

编写 shell 脚本

vim shell.sh

使用vim编辑器新建shell.sh脚本文件。

#!/bin/zsh

echo "Hello world!"
echo "Please input your strings"
read input_string
echo "input_string=$input_string"

脚本首先输出一个“Hello world!”,然后输出一个字符串输入提示语,等待用户输入后,打印出相应的信息。

在 main.c 中调用 shell 脚本

为了在C文件中调用shell脚本,可以使用stdlib.h库中的system函数,调用方式如下:

#include <stdlib.h>
...

void func(void)
{
    system("bash ./<script-filename>.sh");
    // bash为默认shell,也可改用诸如"zsh"类的shell
}

根据该用法修改原有的main.c

#include <stdio.h>
#include <stdlib.h>
#include "main.h"
#include "add.h"

int main(void)
{
    int a = 10;
    int b = 1;
    int c = add(a,b);

    printf("%d + %d = %d\n",a,b,c);
    system("zsh ./shell.sh");     // 调用 shell 脚本

    printf("Infos:File-%s, Func-%s, Line-%d\n",__FILE__,__func__,__LINE__);
    /*
    __FILE__ : 文件名
    __func__ : 函数名
    __LINE__ : 所在行
    */

    return 0;
}

编译链接并执行

$ make clean                # 清除目标文件
rm test main.o add.o

$ make                      # 生成可执行文件
cc    -c -o main.o main.c
cc    -c -o add.o add.c
cc -o test main.o add.o

$ ./test                    # 执行可执行文件
10 + 1 = 11                 # 加法运算结果
Hello world!                # shell 脚本欢迎语
Please input your strings   # 提示语
whatever                    # 手动输入的信息  
input_string=whatever       # 显示信息
Infos:File-main.c, Func-main, Line-14   # 显示打印程序所在文件、函数及对应行数

说明:当使用printf函数时,如果不在输出信息后添加\n换行符的话,其输出信息有可能与shell脚本执行结果发生错位。为避免该情况的发生,应习惯在printf函数调用过程中加入换行符。

显示脚本指令

为了追踪每个脚本指令的执行过程,可以修改system函数调用方式,在bash,zsh后添加选项-x.

system("zsh -x ./shell.sh");

修改后重新执行make,执行./test得到以下结果

$ ./test
10 + 1 = 11
+/etc/zsh/zshenv:15> [[ -z /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin || /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin == /bin:/usr/bin ]]

+./shell.sh:3> echo 'Hello world!'
Hello world!

+./shell.sh:4> echo 'Please input your strings'
Please input your strings

+./shell.sh:5> read input_string
what

+./shell.sh:6> echo 'input_string=what'
input_string=what

Infos:File-main.c, Func-main, Line-14

使用不同的shell,其显示效果不大一致,下面是使用bash执行后的效果。

$ ./test
10 + 1 = 11

+ echo 'Hello world!'
Hello world!

+ echo 'Please input your strings'
Please input your strings

+ read input_string
what

+ echo input_string=what
input_string=what

Infos:File-main.c, Func-main, Line-14

说明:上述执行过程中显示的空行是为了清楚显示执行过程手动添加的,实际执行过程中并无空行。