0. 脚本模板
#!/usr/bin/env bash
#------------------------------------ 1 脚本描述 ----------------------------------
# 用途描述: 批量获取表的存储路径和指定日期路径的大小(默认取昨天的日期)
# 脚本路径: cd /data/dwh_prod/source/shell/common/statistics
# 调用方式: nohup sh -e get_table_locations.sh tables dt > res.log &
#------------------------------------- 2 获取参数 ---------------------------------
## 校验日期
if [[ ${1} = '' ]]
then
dt=$(date +"%Y%m%d" -d "-1 days")
else
dt="${1}"
fi
#------------------------------------- 3 处理逻辑 -------------------------------
for table in ${tables}
do
echo "${table}"
done
1. 抽象--通用化脚本;
2. 参数化--降低硬代码;
1 当前路径
SCRIPT_PATH=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)
2 少回车符
sqls="
aa
bb
"
# a)
echo "${sqls}"
aa
bb
# b)
echo ${sqls}
aa bb
3 定义函数
# 获取最新时间分区
function getNewestDate() {
# 获取传参
local database_table_name=${1}
# 执行命令
local newest_date=$()
# 检测执行状态
if [[ $? -ne 0 ]]
then
echo "fail"
exit 1
fi
# 返回最新日期(不能用return, 该方法中echo只能出现一次)
echo ${newest_date}
}
# 调用函数
date=$(getNewestDate "trandw.dim_pub_tid_event_mapping")
4 读取文件
#1)方式01
while read line
do
echo ${line}
done < filename(待读取文件)
#2)方式02
cat filename(待读取文件) | while read line
do
echo ${line}
done
#3)方式03
for line in `cat filename(待读取文件)`
do
echo ${line}
done
5 软硬链接
linux中软连接和硬链接的区别 - 月光下的脚步 - 博客园
6 序列函数
1 命令参考
linux shell seq命令详解 - 快乐嘉年华 - 博客园
2 循环中使用
# 区间左右都是闭合的
for s in `seq 1987 2018`
do
for m in `seq 1 12`
do
echo ${s}-${m}
done
done
7 条件判断
# 分支判断
if [[ ${group_flag} = small ]]
then
echo "small"
elif [[ ${group_flag} = middle ]]
then
echo "small"
else
echo "fail-组别选择错误"
exit 1
fi
# 变量是否为空
if [[ ! ${sub_paths} ]]
then
echo "变量为空!"
else
echo "变量不为空!"
fi
# 判断上条命令执行状态
if [[ $? = 0 ]]
then
echo "运行成功"
else
echo "运行不成功"
fi
8 循环处理
1 常规参考
# 循环拼接字符串
tables="${1//,/ }"
show_create_tables=''
for table in ${tables}
do
show_create_tables="${show_create_tables} show create table ${table};"
done
# 双层循环
topics="2411 8661"
dhs="00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23"
for topic in ${topics}
do
for dh in ${dhs}
do
echo ${topic}-${dh}
done
done
# 日期循环
## 格式01
start_date="2022-04-06"
end_date="2022-04-07"
while [[ ${start_date} < ${end_date} ]]
do
echo ${start_date}
start_date=$(date -d "${start_date} +1 days" +"%Y-%m-%d")
done
## 格式02
start_date="20220513"
end_date="20221023"
while [[ ${start_date} < ${end_date} ]]
do
echo "{start_date}
start_date=$(date -d "${start_date} +1 days" +"%Y%m%d")
done
2 参考模板
# 获取变量
dt=$(date -d "{{ts}}" +"%Y%m%d")
dh=$(date -d "{{ts}}" +"%H")
online_path="s3://ssjt_shy{{params.region_flag}}/online"
# 获取要添加分区的路径
sub_paths=$(hadoop fs -ls ${online_path}/datax_*/${dt}/ | grep -P "datax_\d{4}/${dt}/${dh}" | awk -F "datax_" '{print $2}')
# 批量添加分区
if [[ ! ${sub_paths} ]]
then
echo "没有分区要添加!"
else
add_partitions="alter table tranods.ods_datax_common_hi add if not exists "
for sub_path in `echo "${sub_paths}"`
do
add_partitions="${add_partitions} partition(dt='${dt}',app_id='${sub_path:0:4}',dh='${dh}') location '${online_path}/datax_${sub_path}'"
done
echo ${add_partitions}
hive -e "${add_partitions};"
fi
9 异常退出
# sh -e 命令调用,对整个被调用的文件有效,执行有异常立即报错退出
sh -e tesh.sh
# set -e shell脚本中的命令,只对set -e 之后的命令有效,其后的命令执行有异常立即报错退出
set -e
注意:不是所有情况下,都要需要碰到错误就退出;
1)需要严格串行执行的
10 操作数组
11 crontab使用
注意事项:
- 增加定时用的环境变量
- 指定解释器
- 用绝对路径调用
- 定时样例:0 11 * * * sh /root/shy/run_timer.sh > /root/shy/time.log 2>&1
# crontab中增加的
source /etc/profile
. ~/.bash_profile
# 指定解释器
#!/bin/bash
# 处理逻辑
echo start
sh /root/shy/metadata_migrate.sh daoru dw
sh /root/shy/metadata_migrate.sh tongji dw
echo end
20 其它汇总
1. 全局命令
# 脚本放到特定目录下,可以全局执行
cd /usr/bin/
mv ossutil64 ossutil
2. 命令可直接运行,无法在脚本中运行
1. 环境变量不同:在脚本中,有些环境变量可能没有被设置,导致命令无法执行。你可以在脚本中加入以下代码:
```bash
#!/bin/bash
source /etc/profile # 加载系统环境变量
source ~/.bash_profile # 加载用户环境变量
source ~/.bashrc
export PATH=$PATH:/usr/local/bin
# 执行命令
```
如果你使用的是其他shell,可以相应地修改加载环境变量的命令。
2. 路径问题:在脚本中,有些命令的路径可能没有被正确设置,导致无法执行。你可以在脚本中使用绝对路径,或者在脚本中添加PATH环境变量:
```bash
#!/bin/bash
export PATH=$PATH:/usr/local/bin # 添加PATH环境变量
# 执行命令
```
这样就可以将/usr/local/bin目录下的命令添加到PATH环境变量中了,如果你使用的命令不在这个目录下,可以相应地修改路径。
3. 权限问题:在脚本中,有些命令可能需要root权限或其他特定的权限才能执行。你可以在脚本中使用sudo命令来提升权限:
```bash
#!/bin/bash
sudo command # 使用sudo命令执行命令
```
如果你不想在脚本中使用sudo命令,可以将需要特定权限的命令放到单独的脚本中,然后在主脚本中使用sudo运行这个脚本。