🎨Bash基础入门与应用

Shell执行方式

bash hello.sh #方式一
cat hello.sh | bash #方式二
bash < hello.sh #方式三
chmod +x hello.sh #方式四
 
#方式五
source hello.sh
#source有一个简写形式,可以使用一个点(.)来表示。
 
#方式六,远程加载执行
curl -s http://localhost/hello.sh |bash
 
#wget方式
wget -qO - http://localhost/hello.sh|bash

配置文件

全局,针对所有用户

/etc/profile
/etc/profile.d/*.sh
/etc/bashrc
 
#只针对个人
~/.bash_profile
~/.bashrc

环境变量

常用环境变量

#显示所有变量以及BASH函数
set

BASHPID:Bash 进程的进程 ID。

DISPLAY:图形环境的显示器名字,通常是:0,表示 X Server 的第一个显示器。

IFS:词与词之间的分隔符,默认为空格。

LANG:字符集以及语言编码,比如zh_CN.UTF-8。

PATH:由冒号分开的目录列表,当输入可执行程序名后,会搜索这个目录列表。

SHELL:Shell 的名字。

SHELLOPTS:启动当前 Shell 的set命令的参数,参见《set 命令》一章。

TERM:终端类型名,即终端仿真器所用的协议。

内置变量:PS1,PATH,UID,HOSTNAME,$$,BASHPID,PPID,$?,HISTSIZE

位置、特殊变量

$1,$2 #对应参数

$0 #命令本身

$* #全部参数命为一个字符串

$@ #每个参数为独立字符串

$# #传递给脚本的参数的个数

$? #0代表成功

$? 值 1-255 #代表失败

$$ #当前SHell的进程ID

$_ #为上一个命令的最后一个参数

$! #为最后一个后台执行的异步命令的进程ID

$- #当前Shell启动参数

$? 是一个特殊变量,用来获取上一个命令的退出状态,或者上一个函数的返回值。

用户自定义变量

#直接字串
name='root'
 
#变量引用
name="$USER"
 
#命令引用
name=`COMMAND`  name=$(COMMAND)

变量引用

· $name

弱引用,变量引用会被替换为变量值

· ${name}

强引用,不会替换为变量值,保持原字符

如果变量的值本身也是变量,使用${!varname}读取最终的值

#环境变量,可用变量传递给子Shll
export name=VALUE
declare -x name=VALUE
 
#删除变量
unset NAME
 
#只读变量,常量
readonly [-p]
declare -r

脚本调试

#只检测语法错误
bash -n hello.sh
 
#调试并执行
bash -x hello.sh

字符串操作

#获取字符串长度
${#varname}
 
#子字符串
${varname:offset:length}
 
#搜索和替换
myccav=/home/ccav/book/administrator.ini
##最短匹配
echo ${myccav#/*/}
ccav/book/administrator.ini
 
##最长匹配
echo ${myccav##/*/}
administrator.ini
 
##只留文件名
echo  ${myccav##*/}
 
#替换,将administrator替换为root,加//替换所有
echo  ${myccav/administrator/root}
 
#转换大写
${varname^^}
 
#转换小写
${varname,,}

判断

注意 [ ] 需要空格,否则会报错误

[ ]和[ [ ] ]的区别是,双括号是增加版,支持正则表达式和通配符

#判断后缀
[[ "$FILE" == *.log ]]
 
#判断合法非负整数
[[ "$N" =~  ^[0-9]+$  ]]
 
#判断合法IP
[[ "$IP" =~  ^([0-9]{1,3}\.){3}[0-9]{1,3}$  ]]
[[ $IP =~ ^(([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$ ]]
-eq 是否等于
-ne 是否不等于
-gt 是否大于
-ge 是否大于等于
-lt 是否小于
-le 是否小于等于
 
-z 字符串是否为空
-n 字符串是否不为空

#判断文件
-a FILE:同 -e
-e FILE: 文件存在性测试,存在为真,否则为假
-b FILE:是否存在且为块设备文件
-c FILE:是否存在且为字符设备文件
-d FILE:是否存在且为目录文件
-f FILE:是否存在且为普通文件
-h FILE  -L FILE:存在且为符号链接文件
-p FILE:是否存在且为命名管道文件
-S FILE:是否存在且为套接字文件
 
#文件权限
-r FILE:是否存在且可读
-w FILE: 是否存在且可写
-x FILE: 是否存在且可执行
-u FILE:是否存在且拥有suid权限
-g FILE:是否存在且拥有sgid权限
-k FILE:是否存在且拥有sticky权限

read

-p 指定要显示的提示

-s 静默输入,一般用于密码

-n N 指定输入的字符长度N

-d '字符' -t N 输入结束符 TIMEOUT为N秒

#输入
read -p "Input Password:" PASSWORD
echo $PASSWORD
 
#判断输入Yes
read -p "Yes or No:" ANSWER
[[ $ANSWER =~ ^([Yy]|[Yy][Ee][Ss])$ ]] && echo "Yes" || echo "No"
 
answer=`echo $input| tr 'A-Z' 'a-z'`
[ $answer = 'yes' -o $answer = 'y' ] && echo YES
[ $answer = 'no' -o $answer = 'n' ] && echo NO

流程控制

#单分支
if 判断条件;then 条件为真的分支代码
fi
 
#双分支
if 判断条件; then 条件为真的分支代码
else
条件为假的分支代码
fi
 
#多分支
if 判断条件1; then 条件1为真的分支代码
elif 判断条件2; then 条件2为真的分支代码
elif 判断条件3; then 条件3为真的分支代码
...
else
  以上条件都为假的分支代码
fi

条件判断case语句

case 变量引用 in PAT1)
分支1
;; PAT2)
分支2
;; ...
*)
;;
esac
 
例子:
case $INPUT in
[yY]|[Yy][Ee][Ss])
echo "Yes"
  ;;
[Nn]|[Nn][Oo])
echo "No"
  ;;
*)
;;
easc

#case多分支
case $option in
1)
select parameter in "a" "b";do
  case $parameter in
  a)
  echo "aaaa"
  break
  ;;
  b)
  echo "bbbb"
  break
  ;;
  easc
2)
...
easc
nmap扫描脚本
nmap 127.0.0.0.1
nmap -sV -Pn 127.0.0.1 -v -n
 
read -p "Input Target:" target
case options in
  1)
  nmap -sV -Pn $target -v -n
  ;;
  2)
  nmap -sV -Pn -p 1-1024,7000-9000 $target -v -n
  ;;
  3)
  nmap -sV -Pn -p1-65535 $target -v -n
  ;;
  4)
  nmap -O -Pn $target
  ;;
esac

循环

#方式1
for 变量名 in 列表;do
循环体
done
 
#方式2
for 变量名 in 列表
do
循环体
done
 
#批量创建用户并设置密码
for i in {1..10};do
useradd user$i
  PASS=`cat /dev/urandom|tr -dc '[:alnum:]'|head -c12`
  echo $PASS |passwd --stdin user$i &> /dev/null
  echo user$i:$PASS >> /data/user.log
  echo "user$i is created"
done  
 
#扫描存活
#!/usr/bin/env bash
for ip in {1..254};do
    ping 192.168.$ip.1 -c 1 |grep -q "ttl=" && echo "192.168.$ip.1 yes" >> /usr/tmp/.sys.log & >/dev/null 2>&1;
done
wait

定义函数

#语法一
func_name(){
...函数体...
}
 
#语法二
function func_name {
...函数体...
}
 
#语法三
function func_name() {
...函数体...
}
查看函数、删除
#查看已定义函数名
declare -F
 
#查看函数内容
declare -f
 
#查看函数内容
declare -f func_name
 
#删除函数
unset func_name
函数调用
#直接写函数名
 
#调用其它脚本中的函数
. filename
or
source filename
防火墙禁用
#防火墙禁用
disable_firewall(){
 systemctl disable --now firewalld &> /dev/null
 echo "防火墙已禁用"
}
扫描目录
#扫描目录
function dirb()
{
  PORT="80"
  /usr/bin/dirb http://$IP:$PORT /usr/share/dirb/wordlists/common.txt
}

Last updated