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");
}