1、判断文件or文件夹
if [ ! -d "${CUR_FOLDER}/logs" ]; then
# 创建日志目录
mkdir -p ${CUR_FOLDER}/logs
if [ $? -ne 0 ]; then
log_warn "日志目录【${CUR_FOLDER}/logs】创建失败" # log_warn是定义的另一个方法
exit 0
fi
fi
代码含义
这个代码片段是一个Shell脚本,用于检查并创建日志目录。具体步骤如下:
- 检查
${CUR_FOLDER}/logs
目录是否存在。 - 如果目录不存在,则创建该目录。
- 检查目录创建是否成功。
- 如果创建失败,输出警告信息并退出脚本。
if
的用法
if
是条件判断语句,用于根据条件的真假来执行不同的代码块。在Shell脚本中,if
语句的基本结构如下:
if [ 条件 ]; then
# 条件为真时执行的代码
else
# 条件为假时执行的代码
fi
!
的含义
!
是逻辑非运算符,用于取反。也就是说,如果条件为真,!
会将其变为假;如果条件为假,!
会将其变为真。在这个代码中,[ ! -d "${CUR_FOLDER}/logs" ]
的意思是“如果 ${CUR_FOLDER}/logs
目录不存在”。
$?
的含义
$?
是一个特殊变量,用于获取上一个命令的退出状态码。通常,命令成功执行返回0,失败返回非0值。在这个代码中,if [ $? -ne 0 ]; then
用于检查上一个命令(即 mkdir -p ${CUR_FOLDER}/logs
)是否成功执行。
d
的含义
d
是一个文件测试选项,用于检查指定路径是否为目录。在这个代码中,[ -d "${CUR_FOLDER}/logs" ]
用于检查${CUR_FOLDER}/logs
是否存在且为目录。
ne
的含义
ne
是数值比较运算符,表示“不等于”。在这个代码中,[ $? -ne 0 ]
的意思是“如果上一个命令的退出状态码不等于0”。
其他常见的文件测试选项
e
:检查文件是否存在。f
:检查是否为普通文件。r
:检查文件是否可读。w
:检查文件是否可写。x
:检查文件是否可执行。
希望这些解释对你有帮助!如果有其他问题,请随时提问。
2、数值判断
在 Shell 脚本中,常见的数值比较运算符包括:
eq
:等于 (equal)ne
:不等于 (not equal)lt
:小于 (less than)le
:小于或等于 (less than or equal)gt
:大于 (greater than)ge
:大于或等于 (greater than or equal)
示例
a=5
b=10
if [ $a -eq $b ]; then
echo "a 等于 b"
fi
if [ $a -ne $b ]; then
echo "a 不等于 b"
fi
if [ $a -lt $b ]; then
echo "a 小于 b"
fi
if [ $a -le $b ]; then
echo "a 小于或等于 b"
fi
if [ $a -gt $b ]; then
echo "a 大于 b"
fi
if [ $a -ge $b ]; then
echo "a 大于或等于 b"
fi
解释
eq
:检查a
是否等于b
。ne
:检查a
是否不等于b
。lt
:检查a
是否小于b
。le
:检查a
是否小于或等于b
。gt
:检查a
是否大于b
。ge
:检查a
是否大于或等于b
。
这些运算符可以帮助你在 Shell 脚本中进行数值比较,从而实现不同的逻辑判断。
3、变量的参数扩展
参数扩展(Parameter Expansion)是 Shell 脚本中非常强大的功能,可以用来操作变量的值。
基本语法
${parameter}
这是最基本的参数扩展,用于获取变量的值。
删除前缀和后缀
-
删除最短匹配的前缀
${variable#pattern}
示例:
file="path/to/myfile.txt" echo ${file#*/} # 输出: to/myfile.txt
-
删除最长匹配的前缀
${variable##pattern}
示例:
file="path/to/myfile.txt" echo ${file##*/} # 输出: myfile.txt
-
删除最短匹配的后缀
${variable%pattern}
示例:
file="path/to/myfile.txt" echo ${file%.*} # 输出: path/to/myfile
-
删除最长匹配的后缀
${variable%%pattern}
示例:
file="path/to/myfile.txt" echo ${file%%/*} # 输出: path
默认值和替换
-
如果变量未定义,则使用默认值
${variable:-default}
示例:
echo ${name:-"default_name"} # 如果 name 未定义,则输出 "default_name"
-
如果变量为空或未定义,则使用默认值
${variable:=default}
示例:
name="" echo ${name:="default_name"} # 如果 name 为空,则输出 "default_name"
-
如果变量未定义,则显示错误信息并退出
${variable:?error_message}
示例:
echo ${name:?"name is not set"} # 如果 name 未定义,则显示错误信息并退出
-
如果变量已定义且不为空,则使用替换值
${variable:+replacement}
示例:
name="John" echo ${name:+"Hello, $name"} # 如果 name 已定义且不为空,则输出 "Hello, John"
字符串操作
-
获取字符串长度
${#variable}
示例:
name="John" echo ${#name} # 输出: 4
-
子字符串提取
${variable:offset:length}
示例:
name="JohnDoe" echo ${name:0:4} # 输出: John
-
字符串替换
${variable/pattern/replacement}
示例:
text="Hello World" echo ${text/World/Shell} # 输出: Hello Shell
-
全局字符串替换
${variable//pattern/replacement}
示例:
text="Hello World World" echo ${text//World/Shell} # 输出: Hello Shell Shell
示例
#!/bin/bash
# 定义变量
file_path="/home/user/docs/file.txt"
# 删除最短匹配的前缀
echo ${file_path#*/} # 输出: home/user/docs/file.txt
# 删除最长匹配的前缀
echo ${file_path##*/} # 输出: file.txt
# 删除最短匹配的后缀
echo ${file_path%/*} # 输出: /home/user/docs
# 删除最长匹配的后缀
echo ${file_path%%/*} # 输出: (空字符串)
# 使用默认值
unset name
echo ${name:-"default_name"} # 输出: default_name
# 获取字符串长度
name="John"
echo ${#name} # 输出: 4
# 子字符串提取
echo ${name:1:2} # 输出: oh
# 字符串替换
text="Hello World"
echo ${text/World/Shell} # 输出: Hello Shell
# 全局字符串替换
text="Hello World World"
echo ${text//World/Shell} # 输出: Hello Shell Shell
这些是参数扩展的一些常见用法,可以帮助你在 Shell 脚本中更灵活地操作变量。
4、> >>>>>
#!/bin/bash
#<:文件输入重定向。
#<<:Here Document,多行输入。
#<<<:Here String,单行字符串输入。
cat>a.txt<<EOF
a
bc
def
EOF
# 示例文件内容
echo -e "file_line1\nfile_line2\nfile_line3" > example.txt
# 使用 < 文件输入重定向
echo "使用 < 文件输入重定向:"
cat < example.txt
# 使用 << Here Document
echo -e "\n使用 << Here Document:"
cat << EOF
doc_line1
doc_line2
doc_line3
EOF
# 使用 <<< Here String
echo -e "\n使用 <<< Here String:"
cat <<< "This is a single line string"
5、一些脚本解读
# cluster.conf示例:
#zk_node_1_host=10.87.102.206
#zk_node_1_port=16871
#zk_node_2_host=10.87.102.207
#zk_node_2_port=16871
. ${CUR_FOLDER}/cluster.conf # 等效于 source ${CUR_FOLDER}/cluster.conf把conf读近配置
. ${CUR_FOLDER}/gen_login_cmd.sh # 执行这个shell、加载一些变量和方法
zk_index=1
while true; do
host_var="zk_node_${zk_index}_host" # host_var
# 检查所有变量是否为空,若有一个为空则跳出循环
if [ -z "${
!host_var}" ]; then
break
fi
# 远程安装jdk、zookeeper
echo $(get_scp_command ${
!host_var} "${DEP_FOLDER}/jdk-8u202-nonroot.tar.gz ${DEP_FOLDER}/apache-zookeeper-3.7.2-bin.tar.gz")
zk_index=$((zk_index + 1)) # 双层是$(())执行一个运算操作 单层是$()执行一个子shell
done
#!/bin/bash
# install.conf示例:
#ssh.10.87.102.206=root:idss:/opt/idss/ck_cluste
#ssh.10.87.102.207=admin:adminpass:/opt/idss/ck_cluste
# 读取配置文件并解析
CONFIG_FILE="install.conf"
declare -A HOSTS # 声明一个关联数组【哈希表、字典】
#-a:声明一个索引数组。
#-A:声明一个关联数组(哈希表)。
#-i:声明一个整数变量。
#-r:声明一个只读变量(只读变量不能被修改)。
#-x:声明一个环境变量(将变量导出到子进程)。
#-l:将变量的值转换为小写。
#-u:将变量的值转换为大写。
#-p:显示变量的属性和值。
while IFS='=' read -r key user_password || [[ -n "$key" ]]; do
key=$(echo "$key" | xargs) # xargs去除前后空格
user_password=$(echo "$user_password" | xargs)
if [[ $key == ssh.* ]]; then
host=${key#ssh.}
HOSTS["$host"]="$user_password"
fi
done < "$CONFIG_FILE" # < 将$CONFIG_FILE中的内容逐行读取并作为while循环的输入。
#<:文件输入重定向。
#<<:Here Document,多行输入。
#<<<:Here String,单行字符串输入。
# 获取 SSH 命令
get_ssh_command() {
local host=$1
local cmd=$2
local user_password=${HOSTS["$host"]}
IFS=':' read -r user password install_path<<< "$user_password"
# read -r key user_password:
# read命令用于从标准输入读取一行,并将其分割成多个变量。
# -r选项告诉read命令不要对反斜杠进行转义。
# user和password、install_path是3个变量,read命令会将等号前的部分赋值给key,等号后的部分赋值给user_password。
echo "sshpass -p '$password' ssh $user@$host $cmd"
}
# 获取 SCP 命令
get_scp_command() {
local host=$1
local files=$2
local user_password=${HOSTS[$host]}
# root:idss:/opt/idss/ck_cluste
IFS=':' read -r user password install_path<<< "$user_password"
mkdir_cmd=$(get_ssh_command $host "mkdir -p $install_path")
`$mkdir_cmd`
echo "sshpass -p '$password' scp -r $files $user@$host:$install_path"
}
# ssh_command=$(get_scp_command "10.87.102.206" "/Users/admin/scripts/dbaudit/ckcluster/dep/jdk-8u202-nonroot.tar.gz /Users/admin/scripts/dbaudit/ckcluster/dep/apache-zookeeper-3.7.2-bin.tar.gz")
# echo $ssh_command
# scp_command=$(get_ssh_command "10.87.102.206" "ls /opt/idss/ck_cluste")
# echo $scp_command
# `$scp_command`