springboot 调用shell脚本,支持传参

import org.apache.commons.lang3.ArrayUtils;

import java.io.BufferedReader;
import java.io.File;
import java.io.InputStreamReader;

/**
 * 执行工具类,可以执行shell脚本
 * @Author: liyongjie
 * @Description:
 * @Date: 2022/8/11 4:58 PM
 */
@Slf4j
public class ExecUtil {
    /**
     * 执行shell脚本,脚本放在项目的resource目录下
     * @param scriptName 脚本文件名,带不带sh后缀都可以
     * @param para 参数数组
     */
    public static void execShell(String scriptName, String ... para) {
        try {

            scriptName = scriptName.endsWith(".sh") ? scriptName : scriptName + ".sh";
            File file = ResourceUtil.getFile("classpath:" + scriptName);
            if (!file.exists()) {
                throw new BizException("脚本文件不存在");
            }
            String scriptPath = file.getAbsolutePath();
            ProcessBuilder pb = new ProcessBuilder("chmod", "+x", scriptPath);
            Process authCmd = pb.start();
            authCmd.waitFor();
            String[] cmd = new String[]{"./" + scriptName};
            //为了解决参数中包含空格
            cmd= ArrayUtils.addAll(cmd,para);
            // 添加操作系统
            cmd = ArrayUtils.add(cmd, getOS());
            pb = new ProcessBuilder(cmd);
            pb.directory(new File(scriptPath.substring(0, scriptPath.length() - scriptName.length() - 1)));
            Process ps = pb.start();
            ps.waitFor();

            BufferedReader stdInput = new BufferedReader(new InputStreamReader(ps.getInputStream()));
            BufferedReader stdError = new BufferedReader(new InputStreamReader(ps.getErrorStream()));
            String s = null;
            while ((s = stdInput.readLine()) != null) {
                log.info("{} script 日志:{}", scriptName, s);
                System.out.println(s);
            }
            while ((s = stdError.readLine()) != null) {
                log.error("{} script 异常:{}", scriptName, s);
                System.out.println(s);
            }
        } catch (Exception e) {
            log.error("exec shell e", e);
        }
    }

    private static String getOS() {
        String property = System.getProperty("os.name");
        if (property.startsWith("Mac")) {
            return "Mac";
        } else if (property.startsWith("Linux")) {
            return "Linux";
        } else if (property.startsWith("Windows")) {
            return "win";
        }
        return "";
    }
}
#!/bin/bash
db_user=root
db_pwd=pwd
db_host=localhost
db_port=3306
db_name=learn
db_table=$1
column=$2
curr_os=$3
time_in_loop="date +%s%N"


echo "host:${db_host} database:${db_name} table:${db_table} column:${column}"
MySQL="/usr/local/mysql/bin/mysql -h${db_host} -u${db_user} -p${db_pwd} -P${db_port} -A -N ${db_name}"
#sql_for_ai="show create table ${db_name}.${db_table}"
#echo ${MySQL} ${sql_for_ai}
#str_temp=$($MySQL -e "$sql_for_ai")
#echo $?
#echo $str_temp

function run() {
    sql_for_ai="show create table ${db_name}.${db_table}"
    echo ${MySQL} ${sql_for_ai}

    str_temp=$(${MySQL} -e "$sql_for_ai")

    if [[ $? -ne 0 ]]; then
      echo "Executing first sql(find the value of auto_increment) wrong! Please check your parameters"
      echo ""
      exit
    fi

    ai_value=$(echo ${str_temp} | grep -oE "AUTO_INCREMENT=[0-9]+" | grep -oE "[0-9]+")
    ai_value_plus_2k=$(($ai_value+2000))

    suffix=`date -d"30 days ago" +"%Y%m%d"`
    st=`date -d"30 days ago" +"%Y-%m-%d 00:00:00"`
    if [ "${curr_os}" == "Mac" ]; then
        echo "兼容Mac系统的日期"
        suffix=`date -v-30d +"%Y%m%d"`
        st=`date -v-30d +"%Y-%m-%d 00:00:00"`
        time_in_loop="date +%s%S"
    fi
    origin_table=${db_table}
    bak_table_name="${origin_table}_bak_${suffix}"

    # 获取当前主表最小id作为归档起始范围
    get_min_id_sql="use ${db_name}; select min(id) from ${origin_table};"
    echo "Get MinId Sql: ${get_min_id_sql}"
    min_id=$(${MySQL} -e "${get_min_id_sql}")
    if [ "${min_id}" == "NULL" ]; then
        echo "minId get ${min_id} to exit"
        exit
    fi
    echo "minId get ${min_id}"

    # 获取主表指定字段30天之前最大id作为归档结束范围
    get_max_id_sql="SELECT max(id) FROM ${origin_table} where ${column} < '${st}';"
    echo "Get MaxId Sql: ${get_max_id_sql}"
    max_id=$(${MySQL} -e "${get_max_id_sql}")
    if [ "${max_id}" == "NULL" ]; then
        echo "maxId get ${max_id} to exit"
        exit
    fi
    echo "maxId get ${max_id}"

    readySql="USE ${db_name}; \
    CREATE TABLE IF NOT EXISTS ${bak_table_name} LIKE ${origin_table};\
    "

    ${MySQL} -e "${readySql}"

    page_size=2000
    if [[ $(( (max_id-min_id)%page_size )) -eq 0 ]]; then
        index=$(( (max_id-min_id)/page_size ))
    else
        index=$(( (max_id-min_id)/page_size+1 ))
    fi
    echo "minId:${min_id}, maxId:${max_id}, index:${index}, page_size:${page_size}"

    # 分批次将范围id的数据从主表迁移至归档表
    for (( i = 0; i < ${index}; ++i )); do
        sync_begin=$((min_id+i*page_size))
        sync_end=$((sync_begin+page_size))
        if [[ ${sync_end} -gt ${max_id} ]]; then
            sync_end=$((max_id+1))
        fi

        insert_sql="insert into ${bak_table_name} select * from ${origin_table} where id >= ${sync_begin} and id < ${sync_end};"
        echo "insert_sql: ${insert_sql}"
        delete_sql="delete from ${origin_table} where id >= ${sync_begin} and id < ${sync_end}"
        echo "delete_sql: ${delete_sql}"
        run_sql="use ${db_name}; ${insert_sql}; ${delete_sql}"
        start_time_in_loop=$[$(${time_in_loop})/1000000]
        ${MySQL} -e "${run_sql}"
        if [[ $? -ne 0 ]]; then
            echo "Executing the above sql wrong"
            exit
        fi
        end_time_in_loop=$[$(${time_in_loop})/1000000]
        echo "round: ${i} $((end_time_in_loop - start_time_in_loop))ms"
    done
}

if [[ "dryrun" == "$3" ]];then
    echo "dryrun"
else
    run
    if [[ "$?" == "0" ]]; then
    	echo "finished";
    else echo "errors when connect to the mysql";
    fi
fi

调用

public static void main(String[] args) throws IOException, InterruptedException {
        execShell("上文的shell文件", "表名", "create_time");
    }
  • 1
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值