Shell:修订间差异
跳到导航
跳到搜索
(未显示同一用户的11个中间版本) | |||
第9行: | 第9行: | ||
====环境变量==== | ====环境变量==== | ||
. ~/.bash_profile | . ~/.bash_profile | ||
source .bash_profile | |||
# 上述一般在 bash 环境下会调用 .bashrc,默认有如下代码: | |||
if [ "$BASH" ]; then | |||
if [ -f ~/.bashrc ]; then | |||
. ~/.bashrc | |||
fi | |||
fi | |||
====特殊变量==== | |||
echo [-ne][字符串] | |||
-n 不输出最后的 \n | |||
-e 启用反斜线转义 | |||
-E 不启用反斜线转义 | |||
{| class="wikitable" | |||
!变量 | |||
!含义 | |||
|- | |||
|$0 | |||
|当前脚本的文件名 | |||
|- | |||
|$n | |||
|传递给脚本或函数的参数。n 表示第几个参数 | |||
|- | |||
|$# | |||
|传递给脚本或函数的参数个数 | |||
|- | |||
|$* | |||
|传递给脚本或函数的所有参数 | |||
|- | |||
|$@ | |||
|传递给脚本或函数的所有参数。被双引号(" ")包含时,与 $* 稍有不同 | |||
|- | |||
|$? | |||
|上个命令的退出状态,或函数的返回值,0=OK | |||
|- | |||
|$$ | |||
|当前 Shell 进程 ID。对于 Shell 脚本,就是这些脚本所在的进程ID | |||
|} | |||
{| class="wikitable" | |||
!$0 | |||
!含义 | |||
! | |||
|- | |||
|0 | |||
|成功 | |||
| | |||
|- | |||
|1 | |||
|一般性錯誤,命令失敗 | |||
|Operation not permitted | |||
|- | |||
|2 | |||
|命令参数或格式错误 | |||
|No such file or directory | |||
|- | |||
|126 | |||
|命令或脚本无执行权限 | |||
|Required key not available | |||
|- | |||
|127 | |||
|命令未找到 | |||
|Key has expired | |||
|- | |||
|130 | |||
|被用戶通过 Ctrl+C 終止(信号 2) | |||
|Owner died | |||
|- | |||
|137 | |||
|被 SIGKILL 信号终止(信号 9) | |||
|No more records (read after end of file) | |||
|} | |||
====转义==== | ====转义==== | ||
*<nowiki>''</nowiki> 单引号,硬转义,所有的shell元字符、通配符都会被关掉。注意,硬转义中不允许出现’(单引号)。 | * <nowiki>''</nowiki> 单引号,硬转义,所有的shell元字符、通配符都会被关掉。注意,硬转义中不允许出现’(单引号)。 | ||
*“” 双引号,软转义,只允许出现特定的shell元字符($,`,\):$用于变量值替换、`用于命令替换、\用于转义单个字符 | *“” 双引号,软转义,只允许出现特定的shell元字符($,`,\):$用于变量值替换、`用于命令替换、\用于转义单个字符 | ||
*\ 反斜杠,转义, 去除其后紧跟的元字符或通配符的特殊意义 | *\ 反斜杠,转义, 去除其后紧跟的元字符或通配符的特殊意义 | ||
第30行: | 第101行: | ||
*错误(stderr)信息转为标准输出 | *错误(stderr)信息转为标准输出 | ||
2>&1 | 2>&1 | ||
*标准输出(stdout)转为文件 | * 标准输出(stdout)转为文件 | ||
1>/tmp/log.txt | 1>/tmp/log.txt | ||
==== 将字符串作为shell命令执行 ==== | ====将字符串作为shell命令执行==== | ||
res=`eval "${CMD}"` | res=`eval "${CMD}"` | ||
==== 将结果作为字符串赋值给变量 ==== | ====将结果作为字符串赋值给变量==== | ||
res=$(echo $ABC) | res=$(echo $ABC) | ||
REDIS_PASSWORD=$(kubectl get secret --namespace kube-nodelm redis -o jsonpath="{.data.redis-password}" | base64 -d) | REDIS_PASSWORD=$(kubectl get secret --namespace kube-nodelm redis -o jsonpath="{.data.redis-password}" | base64 -d) | ||
==== 特殊字符 ==== | ====保持变量换行==== | ||
INFO=$(smem -U root) && echo "$INFO" | |||
====排序保留第一行==== | |||
INFO=$(smem -U root) && echo "$INFO" | head -n 1 && echo "$INFO" | sed '1d' | sort -k7nr | head -n 10 | |||
====特殊字符==== | |||
PA=$(echo -ne '\001') | PA=$(echo -ne '\001') | ||
===代码=== | ===代码=== | ||
====Info==== | ====Info ==== | ||
## m02(10.10.137.188) | ## m02(10.10.137.188) | ||
HOST=`hostname` | HOST=`hostname` | ||
第49行: | 第125行: | ||
IP=`ifconfig | grep 'inet ' | grep -v 'inet 127.0.0.1 ' |awk '/broadcast|Bcast/' | awk '{print $2}'` | IP=`ifconfig | grep 'inet ' | grep -v 'inet 127.0.0.1 ' |awk '/broadcast|Bcast/' | awk '{print $2}'` | ||
echo "$HOST($IP)" | echo "$HOST($IP)" | ||
# network | |||
ETH=$(ls /sys/class/net | awk '/^e/{print}') | |||
# IP | |||
IPV4=$(curl ipv4.icanhazip.com) | |||
====时间==== | ====时间 ==== | ||
## 2022/08/29 16:23:01 | ## 2022/08/29 16:23:01 | ||
TIMEID=`date '+%Y/%m/%d %H:%M:%S'` | TIMEID=`date '+%Y/%m/%d %H:%M:%S'` | ||
第65行: | 第145行: | ||
# date "+%Y-%m-%d %H:%M:%S `echo "abc"`" # 比较常见的用法 | # date "+%Y-%m-%d %H:%M:%S `echo "abc"`" # 比较常见的用法 | ||
====命令行参数判断==== | ====命令行参数判断 ==== | ||
if (( $# >= 1 )); then | if (( $# >= 1 )); then | ||
YM=$1 | YM=$1 | ||
第73行: | 第153行: | ||
fi | fi | ||
YY=`echo $YM |cut -c 1-4` | YY=`echo $YM |cut -c 1-4` | ||
====输入==== | ====输入 ==== | ||
if [ "$1" == "" ];then | if [ "$1" == "" ];then | ||
echo "Not Parameter" | echo "Not Parameter" | ||
第91行: | 第171行: | ||
echo OK | echo OK | ||
fi | fi | ||
====字符比较==== | ==== 字符比较==== | ||
if [ "$HASH_FN" == "$HASH_FN_OLD" ];then | if [ "$HASH_FN" == "$HASH_FN_OLD" ];then | ||
echo "${FN} & ${FN_OLD} Hash Some." | echo "${FN} & ${FN_OLD} Hash Some." | ||
第98行: | 第178行: | ||
fi | fi | ||
==== current directory ==== | ====current directory==== | ||
curdir=$( pwd ) | curdir=$( pwd ) | ||
第140行: | 第220行: | ||
echo ${FN} | echo ${FN} | ||
done | done | ||
====遍历当前目录下的文件==== | ==== 遍历当前目录下的文件==== | ||
for FN in ${FILENAME}* | for FN in ${FILENAME}* | ||
do | do | ||
第150行: | 第230行: | ||
find /u01/* -maxdepth 0 -type f | find /u01/* -maxdepth 0 -type f | ||
==== 读变量列表 ==== | ====读变量列表==== | ||
将本地多个文件复制到多台远程机器上。FN(需同步的本地文件列表),TM(目标机器名称或IP) | |||
<small><nowiki># Copy files to remote machines | |||
FN=( | |||
/home/hdfs/.bashrc | |||
/opt/tez/conf/tez-site.xml | |||
/opt/hadoop/etc/hadoop/tez-site.xml | |||
/opt/hive/conf/hive-site.xml | |||
) | |||
TM=( | |||
hdfs01 | |||
hdfs02 | |||
hdfs03 | |||
) | |||
# source(local) -> target(TM) | |||
# OK --> Sucessed | |||
# | |||
for F in ${FN[*]};do | |||
for T in ${TM[*]};do | |||
echo -n "Copy ${F} to ${T} : " | |||
scp -pq ${F} ${T}:${F} >/dev/null 2>&1 && echo "OK" || echo "Failed" | |||
done | |||
done</nowiki></small> | |||
将上面脚本改变一下,FN 定义可以放在用户登录的环境中,然后执行同步命令 hdcp。 | |||
<small><nowiki>## /bin/zhdcp | |||
## Copy files to remote machines | |||
#!/bin/sh | |||
if [ "${FN}o" == "o" ];then | |||
echo 'FN is NULL.' | |||
exit 1 | |||
fi | |||
TM=( | |||
hdfs01 | |||
hdfs02 | |||
hdfs03 | |||
) | |||
# source(local) -> target(TM) | |||
# OK --> Sucessed | |||
# | |||
for F in ${FN[*]};do | |||
for T in ${TM[*]};do | |||
echo -n "Copy ${F} to ${T} : " | |||
scp -pq ${F} ${T}:${F} >/dev/null 2>&1 && echo "OK" || echo "Failed" | |||
done | |||
done</nowiki></small> | |||
因为 FN 变量无法直接在 shell 中使用,故定义 alias: | |||
<small>alias hdcp='FN="${FN[@]}" zhdcp'</small> | |||
FN=(A B C)相当于定义了一个数组,${FN[0]} 亦可以写作 $FN 的值是 A。${FN[@]} 表示整个数组。 | |||
====循环==== | ====循环==== | ||
CS=2 | CS=2 | ||
第180行: | 第301行: | ||
<nowiki>[[ $string =~ ^$sub.*$]]</nowiki> | <nowiki>[[ $string =~ ^$sub.*$]]</nowiki> | ||
<nowiki>[[ $string =~ ^.*$sub$]]</nowiki> | <nowiki>[[ $string =~ ^.*$sub$]]</nowiki> | ||
====字符串 按分隔符取段 ==== | ====字符串 按分隔符取段==== | ||
# a bc 1 --> a bc | # a bc 1 --> a bc | ||
STR1=${STR1% *}--> a bc | STR1=${STR1% *}--> a bc | ||
第190行: | 第311行: | ||
echo $STR1 |cut -d ' ' -f2 | echo $STR1 |cut -d ' ' -f2 | ||
echo $STR1 |cut -c 1-4 | echo $STR1 |cut -c 1-4 | ||
====计算 ==== | ====计算==== | ||
V1 = $(expr $1 - $2) # 须有空格 | V1 = $(expr $1 - $2) # 须有空格 | ||
let V1=$1-$2 # 须无空格 | let V1=$1-$2 # 须无空格 | ||
第196行: | 第317行: | ||
threads=$(expr `cat /proc/cpuinfo |grep processor|wc -l` - 10) | threads=$(expr `cat /proc/cpuinfo |grep processor|wc -l` - 10) | ||
let c=`cat /proc/cpuinfo |grep processor|wc -l`-10 | let c=`cat /proc/cpuinfo |grep processor|wc -l`-10 | ||
====特殊字符 ==== | ====特殊字符==== | ||
PA=$(echo -ne '\004') | PA=$(echo -ne '\004') | ||
====参数==== | ====参数==== | ||
第207行: | 第328行: | ||
user 0m0.000s | user 0m0.000s | ||
sys 0m0.002s | sys 0m0.002s | ||
====LOG Format ==== | ====LOG Format==== | ||
[[分类:Develop]] | [[分类:Develop]] | ||
[[分类:Linux]] | [[分类:Linux]] | ||
[[分类:Shell]] | [[分类:Shell]] |
2024年12月26日 (四) 09:52的最新版本
Shell 是一个用 C 语言编写的程序,是用户使用 Linux 的桥梁。Shell 既是一种命令语言,又是一种程序设计语言。
Shell 是指一种应用程序,这个应用程序提供了一个界面,用户通过这个界面访问操作系统内核的服务。
Ken Thompson 的 sh 是第一种 Unix Shell。
语法
环境变量
. ~/.bash_profile source .bash_profile # 上述一般在 bash 环境下会调用 .bashrc,默认有如下代码: if [ "$BASH" ]; then if [ -f ~/.bashrc ]; then . ~/.bashrc fi fi
特殊变量
echo [-ne][字符串] -n 不输出最后的 \n -e 启用反斜线转义 -E 不启用反斜线转义
变量 | 含义 |
---|---|
$0 | 当前脚本的文件名 |
$n | 传递给脚本或函数的参数。n 表示第几个参数 |
$# | 传递给脚本或函数的参数个数 |
$* | 传递给脚本或函数的所有参数 |
$@ | 传递给脚本或函数的所有参数。被双引号(" ")包含时,与 $* 稍有不同 |
$? | 上个命令的退出状态,或函数的返回值,0=OK |
$$ | 当前 Shell 进程 ID。对于 Shell 脚本,就是这些脚本所在的进程ID |
$0 | 含义 | |
---|---|---|
0 | 成功 | |
1 | 一般性錯誤,命令失敗 | Operation not permitted |
2 | 命令参数或格式错误 | No such file or directory |
126 | 命令或脚本无执行权限 | Required key not available |
127 | 命令未找到 | Key has expired |
130 | 被用戶通过 Ctrl+C 終止(信号 2) | Owner died |
137 | 被 SIGKILL 信号终止(信号 9) | No more records (read after end of file) |
转义
- '' 单引号,硬转义,所有的shell元字符、通配符都会被关掉。注意,硬转义中不允许出现’(单引号)。
- “” 双引号,软转义,只允许出现特定的shell元字符($,`,\):$用于变量值替换、`用于命令替换、\用于转义单个字符
- \ 反斜杠,转义, 去除其后紧跟的元字符或通配符的特殊意义
*在“”中不用使用转义,但再次使用时,变量应该加“”,如:
c="a * b" echo "$c"
与或非
- 与 && 或: -a
- 或 || 或: -o
- 非 !
根据结果分支
grep -q sse4_2 /proc/cpuinfo && echo "SSE 4.2 supported" || echo "SSE 4.2 not supported"
输出
- 错误(stderr)信息转为标准输出
2>&1
- 标准输出(stdout)转为文件
1>/tmp/log.txt
将字符串作为shell命令执行
res=`eval "${CMD}"`
将结果作为字符串赋值给变量
res=$(echo $ABC) REDIS_PASSWORD=$(kubectl get secret --namespace kube-nodelm redis -o jsonpath="{.data.redis-password}" | base64 -d)
保持变量换行
INFO=$(smem -U root) && echo "$INFO"
排序保留第一行
INFO=$(smem -U root) && echo "$INFO" | head -n 1 && echo "$INFO" | sed '1d' | sort -k7nr | head -n 10
特殊字符
PA=$(echo -ne '\001')
代码
Info
## m02(10.10.137.188) HOST=`hostname` IP=`ping $HOST -c1|xargs|awk -F')' '{print $1}'|awk -F'(' '{print $2}'` - OR - IP=`ifconfig | grep 'inet ' | grep -v 'inet 127.0.0.1 ' |awk '/broadcast|Bcast/' | awk '{print $2}'` echo "$HOST($IP)" # network ETH=$(ls /sys/class/net | awk '/^e/{print}') # IP IPV4=$(curl ipv4.icanhazip.com)
时间
## 2022/08/29 16:23:01 TIMEID=`date '+%Y/%m/%d %H:%M:%S'` DATEID=`date +%Y%m%d` DATEID=`date -dyesterday +%Y%m%d` DATEID=`date -dtomorrow +%Y%m%d` DATEID=`date -d "$date last month" +%Y%m%d` DATEID=`date -d "$date next month" +%Y%m%d` DATEID=`date -d "$date -1 day" +%Y%m%d` DATEID=`date -d "$date -1 month" +%Y%m%d` # date "+%Y-%m-%d %H:%M:%S `echo "abc"`" # 比较常见的用法
命令行参数判断
if (( $# >= 1 )); then YM=$1 else echo $0 'YM=yyyymm' exit 1 fi YY=`echo $YM |cut -c 1-4`
输入
if [ "$1" == "" ];then echo "Not Parameter" fi
if [ "$1" == "" ]; then CS=1 #elif … ; then else CS=$1 fi
数值比较
if ((${PS} > 0)); then echo "Task: $CMD exist." exit 1 else echo OK fi
字符比较
if [ "$HASH_FN" == "$HASH_FN_OLD" ];then echo "${FN} & ${FN_OLD} Hash Some." else echo "Backup ${HASH_FN} Finished." fi
current directory
curdir=$( pwd ) curdir="$(cd "$(dirname "${BASH_SOURCE[0]}")" &>/dev/null && pwd)" BASH_SOURCE[0] 等价于 BASH_SOURCE, 取得当前执行的 shell 文件所在的路径及文件名。 上一级目录 predir="$( cd .. pwd )"
file or path exist
## if file exist, run [ -f /etc/profile ] && source /etc/profile # if path not exist, create [ ! -d $VPATH ] && mkdir -p $VPATH -e filename 如果 filename存在,则为真 -d filename 如果 filename为目录,则为真 -f filename 如果 filename为常规文件,则为真 -L filename 如果 filename为符号链接,则为真 -r filename 如果 filename可读,则为真 -w filename 如果 filename可写,则为真 -x filename 如果 filename可执行,则为真 -s filename 如果文件长度不为0,则为真 -h filename 如果文件是软链接,则为真
按行读文件
while read LN do echo ${LN} done < ${LN_NAME} cat ${LN_NAME} | while read LN do echo $LN done for FN in ${LN_NAME} do echo ${FN} done
遍历当前目录下的文件
for FN in ${FILENAME}* do echo ${FN} done
遍历当前目录下的目录
find /u01/* -maxdepth 0 -type d # 遍历当前目录下的文件 find /u01/* -maxdepth 0 -type f
读变量列表
将本地多个文件复制到多台远程机器上。FN(需同步的本地文件列表),TM(目标机器名称或IP)
# Copy files to remote machines FN=( /home/hdfs/.bashrc /opt/tez/conf/tez-site.xml /opt/hadoop/etc/hadoop/tez-site.xml /opt/hive/conf/hive-site.xml ) TM=( hdfs01 hdfs02 hdfs03 ) # source(local) -> target(TM) # OK --> Sucessed # for F in ${FN[*]};do for T in ${TM[*]};do echo -n "Copy ${F} to ${T} : " scp -pq ${F} ${T}:${F} >/dev/null 2>&1 && echo "OK" || echo "Failed" done done
将上面脚本改变一下,FN 定义可以放在用户登录的环境中,然后执行同步命令 hdcp。
## /bin/zhdcp ## Copy files to remote machines #!/bin/sh if [ "${FN}o" == "o" ];then echo 'FN is NULL.' exit 1 fi TM=( hdfs01 hdfs02 hdfs03 ) # source(local) -> target(TM) # OK --> Sucessed # for F in ${FN[*]};do for T in ${TM[*]};do echo -n "Copy ${F} to ${T} : " scp -pq ${F} ${T}:${F} >/dev/null 2>&1 && echo "OK" || echo "Failed" done done
因为 FN 变量无法直接在 shell 中使用,故定义 alias:
alias hdcp='FN="${FN[@]}" zhdcp'
FN=(A B C)相当于定义了一个数组,${FN[0]} 亦可以写作 $FN 的值是 A。${FN[@]} 表示整个数组。
循环
CS=2 for (( i=1; i<=${CS}; i++ )) do echo $i done
字符串 子串
# 包含 [[ $string =~ $sub]] # 开头 [[ $string = $sub*]] # 结束 [[ $string = *$sub]] # 正则 [[ $string =~ ^.*$sub.*$]] [[ $string =~ ^$sub.*$]] [[ $string =~ ^.*$sub$]]
字符串 按分隔符取段
# a bc 1 --> a bc STR1=${STR1% *}--> a bc STR1=${STR1%% *} --> a # a bc 1 --> bc 1 STR1=${STR1#* } STR1=${STR1##* } --> 1 # cut echo $STR1 |cut -d ' ' -f2 echo $STR1 |cut -c 1-4
计算
V1 = $(expr $1 - $2) # 须有空格 let V1=$1-$2 # 须无空格
计算主机线程数-10
threads=$(expr `cat /proc/cpuinfo |grep processor|wc -l` - 10) let c=`cat /proc/cpuinfo |grep processor|wc -l`-10
特殊字符
PA=$(echo -ne '\004')
参数
管道
read VAR1 # 可从标准输入或管道接收
sleep
time sleep 0.030 real 0m0.032s user 0m0.000s sys 0m0.002s