Linux执行程序脚本,以及自动生成相关脚本

Linux上自动执行程序脚本

自动执行程序的脚本:

启动程序的shell脚本
#!/bin/bash

run_program() {
	#表示第一个参数
    program=$1
    program_path="./$program"
	# 去掉扩展名,拼接成 XXX_log 的形式
    log_file="${program%%.*}_log"

    chmod 777 "$program_path"

	# 检查该程序后台是否正在运行
    pid=$(pgrep -f "$program_path")

    # 如果后台正在运行就kill掉该程序
    if [ -n "$pid" ]; then
        sudo kill "$pid" > /dev/null 2>&1
        sleep 1    # kill掉之后休息1秒钟,等待清理资源
    fi

	# 启动该程序,并将结果重定向到log文件,"2>&1" 表示将标准错误重定向到标准输出所指向的位置,即log文件
	# 最后一个 "&" 表示把前面的整个命令放到后台执行,不会阻塞脚本的继续执行,否则会阻塞脚本,直到程序运行结束
    sudo "$program_path" >> "$log_file" 2>&1 &
}

----

# 根据需要添加要启动的程序
run_program "s1.out"
run_program "s2.out"

在程序中自动生成该脚本

在一些场景下需要自动生成这样的脚本,并下载对应的Linux设备上,让用户实现一键式部署,无需再手动的修改启动脚本,对应的生成脚本代码如下:

生成脚本代码
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <sstream>

using std::string;
using std::vector;

void WriteShell(const vector<string>& vec, const string& fileName);

int main()
{
    string fileName = "D:/Tmp/start.sh";
    vector<string> vec = { "s1.out","s2.out","s3.out" };
    WriteShell(vec, fileName);
}

void WriteShell(const vector<string>& vec, const string& fileName)
{
    std::stringstream sstr;

    // 1-1. 写入固定部分的内容,原始字符串: R"delimiter(content)delimiter"
    sstr << R"----(#!/bin/bash

# This script was generated dynamically by a C++ program.

run_program() {
    program=$1
    program_path="./$program"
    # 将日志文件名后缀改为 .log
    log_file="${program%%.*}.log"

    echo "Handling program: $program"

    # 赋予执行权限
    chmod +x "$program_path"

    # 使用 pgrep 查找进程
    pid=$(pgrep -f "$program_path")

    # 检查进程是否存在
    if [ -n "$pid" ]; then
        echo "Process for $program found with PID: $pid. Attempting to kill."
        sudo kill "$pid" > /dev/null 2>&1
        sleep 1
    fi

    echo "Starting $program in background. Log will be at $log_file"
    
    sudo "$program_path" >> "$log_file" 2>&1 &
}

)----";

    // 1-2. 将动态的变量写入脚本
    for (const auto& str : vec)
    {
        sstr << "run_program \"" << str << "\"\n";
    }

    // 1-3. 写入结束提示信息
    sstr << "\necho \"Shell excute finished.\"\n";

    //2. 将文件写入到本地文件中

    // 2-1. 从stringstream中获取获取完整的字符串
    string resContentStr = sstr.str();

    // 2-2. 以二进制模式打开文本文件,保证Linux格式的换行符(LF),
    // 避免在Windows上写入换行符 "\n"时,C++将其转换成 "\r\n",然后在Linux上运行该脚本时,由于多了"\r"导致报错:"command not found: ^M"
    // std::ios::binary,我们告诉文件流:“不要做任何换行符转换,字符串里是什么字节,就原封不动地写入文件
    std::ofstream out(fileName, std::ios::binary);
    if (!out)
    {
        std::cerr << "Error: unable to open file" << std::endl;
        return;
    }

    out << resContentStr;
    out.close();
}

【注意】

  1. 写入代码中,要插入的固定代码部分建议使用原始C++11的字符串,能够直观的显示原始的格式和字符。
  2. 写入时以std::ios::binary格式打开文件,避免在Windows上的自动 \r\n换行符无法被Linux识别的问题
posted @ 2025-07-30 10:19  Jeffxue  阅读(58)  评论(0)    收藏  举报