Bash 101
一、使用场景
一个命令行环境,方便用户使用Linux系统的功能
二、符号
查看当前shell:echo $SHELL
查看当前shell 版本:echo $BASH_VERSION
空格:用于区分不同的参数,如果有多个空格,会忽略
分号:命令结束符,可以在一行放置多个命令,比如clear;ls
&&:command1 && command2,如果第一个命令成功,才会执行第二个命令
||:command1 || command2,如果第一个命令失败,才会执行第二个命令
只有一种数据类型:字符串
通过\转义,如果要转义\,则使用\
单引号:特殊字符放在单引号中,会变成普通字符
双引号:多行文本、保持输出格式
Here文档:<<开始标记,结束标记,作为命令的参数
Here字符串:<<<,将字符串通过标准输入,传递给命令
(()):算数运算,等同于expr命令
三、通配符
?:表示单个字符,如果匹配多个字符,则需要多个?连用
*:任意数量的任意字符
[]:[ab]匹配a或b,[^ab],[!ab]不匹配a、b;[a-z]或[0-9]表示一个连续的范围
{}:{a,b}匹配a和b;mkdir {2022..2024}-{01..12,创建36个目录,格式为年-月
四、变量
环境变量:$HOME、$HOST、$IFS、$SHELL、$HISTSIZE
自定义变量:
创建:a=’test’
访问:echo ${a}
删除:a=’’
特殊变量:
$?:0代表上一个命令执行成功,其他代表失败
$$:当前shell的id进程
$_:上一个命令的最后一个参数
$0:当前shell的名称
declare:为变量设置限制
-i:声明整数变量
-r:声明只读变量
-a:声明关联数组,declare -a test=(‘1‘,’2’,’3’)
变量大小写:大写-${varname^^},小写-${varname,,}
五、数组
arrayName=(a b c)
declare -a arrayName=(a b c)
读取单个元素:arrayName[index]
读取所有元素:arrayName[@]或者arrayName[*]
获取数组长度:echo ${#arrayName[@]}
提取数组序号:${!arrayName[@]}
追加数组:arrayName+=(e d f)
删除数组:unset arrayName[index]
六、条件判断
if commands; then
commands
elif [commands]; then
commands
else
commands
case expression in
pattern)
commands
;;
pattern)
commands
;;
esac
七、循环
break:终止循环
continue:继续下一个循环
while condition; do
commands
done
for variable in list; do
commands
done
for((expression1; expression2; expression3)); do
commands
done
八、函数
$1-$9:函数的第1到第9个参数
$#:参数总数
$@:全部参数,参数之间用空格分隔
$*:全部参数,参数之间用IFS变量分隔
local:声明局部变量
fn() {
codes
}
function fn() {
codes
}
九、文件判断
[-a file]:
如果文件存在,则为true,已废弃[-d file]:如果文件存在且为目录,则为true
[-e file]:如果文件存在,则为true
[-f file]:如果文件存在且为一个普通文件,则为true
[-r file]:如果文件存在且可读,则为true
[-w file]:如果文件存在且可写,则为true
[-x file]:如果文件存在且可执行,则为true
十、脚本
指定解释器:#!/bin/bash 或者 #!/usr/bin/env bash
赋予脚本执行权限:chmod +x test.sh
赋予脚本执行、读权限:chmod +rx test.sh
注释:#
重新加载一个配置文件:source filename
别名: alias
读取用户输入:read [-options] [variable…],
-a :把用户的输入赋值给一个数组;
-r:不把用户输入的反斜杠解释为转义字符
IFS:修改分隔标志,默认是空格
十一、Secure Copy(scp)
ssh协议的文件传输命令,可以在本地主机和远程主机之间安全的复制文件和目录
scp [options] source_path destination_path
从本地复制到远程主机:
scp local_file.txt user@remote_host:/path/on/remote/host
递归复制目录
scp -r local_directory user@remote_host:/path/on/remote/host
十二、Bash脚本示例
将本地物料上传到多个主机
安装sshpass,使用密码进行远程登录
brew install hudochenkov/sshpass/sshpass
#!/usr/bin/env bash
#遇到不存在的变量,终止
set -u
#遇到错误,终止
set -e
echo -n "Enter password for remote server: "
read -s PASSWD
declare -a servers=("user@ip" "user@ip2")
# 获取当前目录所在绝对路径
current_dir=$(pwd)
echo "当前目录: $current_dir"
# 获取需要复的到目录
source_dir="$current_dir/files/"
# 远程主机目录
target_dir="/remote_dir"
echo "源目录: $source_dir"
for server in "${servers[@]}"; do
echo "正在复制到: $server"
# tar打包文件
tar -czf files.tar.gz -C $source_dir .
# 使用密码,上传文件到远程主机
sshpass -p $PASSWD scp files.tar.gz $server:$target_dir
# 使用密码登录到主机并解压文件
sshpass -p $PASSWD ssh $server "cd $target_dir && tar -xzf files.tar.gz && rm files.tar.gz"
# 删除本地文件
rm files.tar.gz
done
echo "上传成功"