shell大全

命令解析器——例如bash

是一个程序,可以解析shell命令

shell基本语法

变量

环境变量

  • 敲命令“env”可以取出所有环境变量
  • 环境变量可以当全局变量来使用
  • set命令可以输出当前系统的全部环境变量以及函数
  • unset命令用于删除一个环境变量

本地变量

自定义的变量——局限在某个脚本中使用

1、变量定义:

  • shell中的变量没有数据类型 - 默认值都是string类型
VAR=hello  or VAR=“hello”

注意事项:

  • 定义shell变量的时候,建议变量名大写
  • 赋值的时候=前后不能有空格

2、一些命令实例

将一个命令执行之后的结果赋值给某个变量(下面两种方式都可以)

var=`pwd`
var=$(pwd)

算术运算(只能在整型之间做算数运算)

var=9
var=$((var+10))
var=$[var+10]

export命令可以把本地变量导出为环境变量

export VARNAME  //只在当前终端中有效
export VARNAME=value

位置变量

  • $0         -   相当于C语言main函数的argv[0]
  • $1、$2...相当于C语言main函数的argv[1]、argv[2]...

特殊变量

  • $#: 这个程序的参数个数
  • $*: 表示参数列表"$1" "$2" ...
  • $@:  表示参数列表"$1" "$2" ...
  • $$: 这个程序的PID
  • $?: 执行上一个命令的返回值

注意!!!加上“”之后,$*和$@会发生变化!!!

  • for循环时候"$*" 将所有的参数作为一个整体
  • for循环时候"$@" 有多少个参数被拆分成几部分

命令代换

 

将执行完命令之后得到的数据保存到变量

VAR=`shell命令`
VAR=$(shell命令) -- 常用,推荐使用

 

算术代换

1、对变量取值

在变量的前边加 $

$VAR

2、对变量做算术运算

  • 算术运算: +-*/
  • 算术运算操作的必须是整数
  • VAR=$(($VAR*10))
  • VAR=$[$VAR-10]

3、进制运算

$[base#n]     数值按照几进制进行运算
  • base - 进制
  • #连接符
  • n:数值

转义字符

\

  • 将有特殊意义的字符变成普通字符
  • 将普通字符变成有特殊意义的字符 - 正则表达式中使用

单引号

VAR='$(date)'

单引号中的内容原样输出

双引号

VAR="$(date)"

会继续双引号中的命令, 输出结果字符串

条件测试

条件测试命令

下面两种方式皆可

  • test
  • [ ]

比较 test , [] , [[]]

  • test [ 是 bash 的内部命令
  • [[ 是 bash 程序语言的关键字
  • 绝大多数情况下,这个三个功能通用。但是命令和关键字总是有区别的。

区别:

  • [[ 中使用 && ||
  • [ 中使用 -a -o 表示逻辑与和逻辑或

如何判断条件是否成立?

  • 如果返回值为0: 成立
  • 返回值为非0:    不成立

例子:

上图中pwd执行成功了,因此返回值是0

文件状态测试

linux中的文件种类: 7种

  • 普通文件:  f
  • 目录: d
  • 符号链接: l
  • 套接字:s
  • 管道:p
  • 字符设备:c
  • 块设备:b

-b filename

当filename 存在并且是块文件时返回真(返回0)

-c filename

当filename 存在并且是字符文件时返回真

-d pathname

当pathname 存在并且是一个目录时返回真

-e pathname

当由pathname 指定的文件或目录存在时返回真

-f filename

当filename 存在并且是正规(普通)文件时返回真

-g pathname

当由pathname 指定的文件或目录存在并且设置了SGID 位时返回真

-h/-L filename

当filename 存在并且是符号链接文件时返回真 (或  filename)

-k pathname

当由pathname 指定的文件或目录存在并且设置了"粘滞"位时返回真

-p filename

当filename 存在并且是命名管道时返回真

-r pathname

当由pathname 指定的文件或目录存在并且可读时返回真

-s filename

当filename 存在并且文件大小大于0 时返回真

-S filename

当filename 存在并且是socket 时返回真

-t fd

当fd 是与终端设备相关联的文件描述符时返回真

-u pathname

当由pathname 指定的文件或目录存在并且设置了SUID 位时返回真

-w pathname

当由pathname 指定的文件或目录存在并且可写时返回真

-x pathname

当由pathname 指定的文件或目录存在并且可执行时返回真

-O pathname

当由pathname 存在并且被当前进程的有效用户id 的用户拥有时返回真(字母O 大写)

-G pathname

当由pathname 存在并且属于当前进程的有效用户id 的用户的用户组时返回真

file1 -nt file2

file1 比file2 新时返回真

file1 -ot file2

file1 比file2 旧时返回真

f1 -ef f2

files f1 and f2 are hard links to the same file

例如,测试文件filename是否为目录文件

常见字符串测试

-z string

字符串string 为空串(长度为0)时返回真

-n string

字符串string 为非空串时返回真

str1 = str2

字符串str1 和字符串str2 相等时返回真

str1 == str2

同 =

str1 != str2

字符串str1 和字符串str2 不相等时返回真

常见的数值测试

  • ==—— eq  —— equal
  • !=——ne—— not equal
  • >——gt  —— greater than
  • >=——ge——greater than equal
  • <——lt   ——less than
  • <=—— le —— less than equal

nt1 -eq int2

如果int1 等于int2,则返回真

int1 -ne int2

如果int1 不等于int2,则返回真

int1 -lt int2

如果int1 小于int2,则返回真

int1 -le int2

如果int1 小于等于int2,则返回真

int1 -gt int2

如果int1 大于int2,则返回真

int1 -ge int2

如果int1 大于等于int2,则返回真

测试时使用的逻辑操作符

  • a - &&  : and
  • o - ||: or
  • 取反:

-a

逻辑与,操作符两边均为真,结果为真,否则为假。

-o

逻辑或,操作符两边一边为真,结果为真,否则为假。

!

逻辑否,条件为假,结果为真。

 shell脚本语法 - 分支

if/then/elif/else/fi

语法格式

if [ 条件判断语句 ];then
    处理语句
    处理语句
elif [ 条件判断语句 ]
then
    处理语句
    处理语句
else
    处理语句
    处理语句
fi

 

:——是一个特殊的命令,称为空命令

  • 该命令不做任何事,但Exit Status总是真。
if :; then

xxxx

fi

 

case/esac

基本语法

case 变量 in
yes|Yes|y|Y)
    处理语句
    处理语句
    ;; 
No|no|n|N)
    处理语句
    处理语句
    ;;
*)
    处理语句
    ;;
esac
  • *类似于default
  • case类似于switch
  • ::类似于break

例子

a.sh
./a.sh   aa

VAR=$1
case VAR in
a*|AA|a|A)
	echo "a"
	;;
b|bb|BB)
	echo b
	;;
*)
	echo "hello"
	;;
esac

 shell脚本语法 - 循环

for/do/done

语法格式

for 变量 in list(列表);do
	控制语句
	控制语句
done

例子(下面两个for循环的结果相同)

for VAR in $(ls) ;do
    echo $VAR
done


for VAR in `ls` ;do
    echo $VAR
done

while/do/done

语法格式

while [ 条件测试语句 ];do
	控制语句
	控制语句
done

例子——输入三次密码,三次错误退出程序

PWD=world
count=1

echo "请输入密码"
read TMP

while [ $TMP != $pwd -a $count le 3 ];do
    echo "密码错误,请重新输入"
    read TMP
    count=$[count+1]
do

break和continue

break 可以选择跳出的层数

break n

输入和输出

echo

echo 字符串
  • -e: 解析字符串中的\n字符
  • -n:去掉echo默认加上的换行符

例子:

文件重定向

cmd > file
  • file - 文件名
cmd >> file
  • 内容追加到file文件中    

例子——将指令cmd的标准输出(1)重定向到file,标准错误(2)重定向到标准输出(1)——标准输出和标准错误都写入file文件中

cmd > file 2>&1

#等价于

cmd 1 > file 2 > &1
  • 1前面加&代表1是文件描述符,不加&,则1代表一个文件

 awk

处理行和列,主要用于列的处理

1、awk缺省的行分隔符是换行

2、缺省的列分隔符是连续的空格和Tab

3、如何取出每一列

  • $0: 当前,还没有拆分
  • $1: 第一列
  • $2: 第二列
  • 。。。。。

4、如果不是缺省分隔符的如何指定分隔符

  • -F后边跟的就是指定的分隔符

5、例子——拆分/etc/passwd,找到每个用户对应的家目录

awk -F: '{print $6}'  /etc/passwd

一般格式

awk 参数 '/pattern/{actions}'   目标文件

awk 参数   'condition{actions}'   目标文件

awk 参数 脚本文件 目标文件
  • condition -- 条件
  • pattern -- 正则表达式
  • actions -- 匹配成功后的一系列操作

例子——找出以g开头的字符串的第三列

awk -F/ '/^g/{print $3}'  test

如何定义变量

  • 需要变量直接写即可,默认值0
  • 定义变量的时候直接指定一个初始值——利用“-v”设定初始值
awk -v x=10  '条件/正则表达式{action} ' 文件名

练习:从ps aux得到的数据中找出pid>1000 && pid <2000的进程的个数

第一步——找出所有进程号在1000到2000之间的进程

ps -aux |  awk '$2>1000 && $2<2000{print $2}'

第二步,设置变量x(x的默认值为0),用于记录当前符合条件的进程号是第几个符合条件的

ps -aux |  awk '$2>1000 && $2<2000{print $2; x=x+1; print x}'

第三步,添加条件END(END——代表遍历结束

ps -aux |  awk '$2>1000 && $2<2000{x=x+1}END{print x}'

shell脚本例子一

#!/bin/bash

# 关闭tracker 和 storage服务
#shell脚本没有返回值,没有参数,但是可以传参
tracker_start()
{
    #查找名为fdfs_trackerd的进程; grep -v grep的意思是过滤掉grep进程
    #> /dev/null重定向到垃圾回收站,扔进去之后,输出就没有了
    ps aux | grep fdfs_trackerd | grep -v grep > /dev/null
    #如果查到了该进程,则$?的值是0
    if [ $? -eq 0 ];then
        echo "fdfs_trackerd 已经在运行中, 无需启动..."
    else
    #说明该进程没有被启动
        sudo fdfs_trackerd  /etc/fdfs/tracker.conf
        if [ $? -ne 0 ];then
            echo "tracker start failed ..."
        else
            echo "tracker start success ..."
        fi
    fi
}

storage_start()
{
    ps aux | grep fdfs_storaged | grep -v grep > /dev/null
    if [ $? -eq 0 ];then
        echo "fdfs_storaged 已经在运行中, 无需启动..."
    else
        sudo fdfs_storaged  /etc/fdfs/storage.conf
        if [ $? -ne 0 ];then
            echo "storage start failed ..."
        else
            echo "storage start success ..."
        fi
    fi
}

#如果没传入参数
if [ $# -eq 0 ];then
    echo "Operation:"
    echo "  start storage please input argument: storage"
    echo "  start tracker please input argument: tracker"
    echo "  start storage && tracker please input argument: all"
    echo "  stop storage && tracker input argument: stop"
    exit 0
fi


case $1 in
    storage)
        storage_start
        ;;
    tracker)
        #调用shell函数tracker_start
        tracker_start
        ;;
    all)
        storage_start
        tracker_start
        ;;
    stop)
        sudo fdfs_trackerd /etc/fdfs/tracker.conf stop
        sudo fdfs_storaged /etc/fdfs/storage.conf stop
        ;;
    *)
        echo "nothing ......"
esac

get技能

1、   grep -v grep    ——过滤掉grep

2、> /dev/null——将输出扔掉

shell脚本例子二

#!/bin/bash
#定义变量
START=1
STOP=1

case $1 in
    start)
        START=1
        STOP=0
        ;;
    stop)
        START=0
        STOP=1
        ;;
    "")
        STOP=1
        START=1
        ;;
    *)
        STOP=0
        START=0
        ;;
esac

# **************************** 杀死正在运行的CGI进程 **************************** 
if [ "$STOP" -eq 1 ];then
    # 登录
    kill -9 $(ps aux | grep "./bin_cgi/login" | grep -v grep | awk '{print $2}') > /dev/null 2>&1

    echo "CGI 程序已经成功关闭, bye-bye ..."
fi


# ******************************* 重新启动CGI进程 ******************************* 
if [ "$START" -eq 1 ];then
    # 登录   -n代表不加换行
    echo -n "登录:"
    spawn-fcgi -a 127.0.0.1 -p 10000 -f ./bin_cgi/login
    echo "CGI 程序已经成功启动 ^_^..."
fi

get技能

1、> /dev/null 2>&1——将标准输出和标准错误全都扔掉

2、 echo -n ——不加换行

shell脚本例子三

#!/bin/bash

NAME=redis
FILE=redis.pid

# 判断redis目录是否存在, 如果不存在则创建
is_directory()
{
	#如果传入的第一个参数不是目录
    if [ ! -d $1 ]; then
        echo "$1 目录创建中..."
        mkdir $1
        if [ $? -ne 0 ];then
            echo "$1 目录创建失败, ~~~~(>_<)~~~~"
            exit 1
        fi
    fi
}

# 判断redis目录是否存在, 如果不存在则创建
is_regfile()
{
    if [ ! -f $1 ]; then
        #statements
        echo "$1 file not exist..."
        return 1
    fi
    return 0
}

# 根据参数设置redis状态
#提示用户需要传入参数
if [[ $1 = "" ]];then
    echo "please input argument:"
    echo "  start: start redis server"
    echo "  stop: stop redis server"
    echo "  status: show the redis server status"
    exit 1
fi

# 函数调用,函数传入的参数是$NAME
is_directory $NAME

case $1 in
    start)
        # 判断 redis-server 进程是否已经启动...
        ps aux | grep "redis-server" | grep -v grep > /dev/null
        if [ $? -eq 0 ];then
            echo "Redis server is runing ..."
        else
            # 删除$FILE 文件
            unlink "$NAME/$FILE"

            echo "Redis starting ..."
            redis-server ./conf/redis.conf
            if [ $? -eq 0 ];then
                echo "Redis server start success!!!"
                # 休眠1s, 等待pid文件被创建出来, 再进行后续判断
                sleep 1
                if is_regfile "$NAME/$FILE";then
				    # printf是一个命令,用于在中断进行输出
                    printf "****** Redis server PID: [ %s ] ******\n" $(cat "$NAME/$FILE")
                    printf "****** Redis server PORT: [ %s ] ******\n" $(awk '/^port /{print $2}' "./conf/redis.conf")
                fi
            fi
        fi
        ;;
    stop)
        # 判断 redis-server 进程是否已经启动...
        ps aux | grep "redis-server" | grep -v grep > /dev/null
        if [ $? -ne 0 ];then
            echo "Redis server is not runing..."
            exit 1
        fi
        echo "Redis stopping ..."
        # 判断pid文件是否存在
		#调用函数is_regfile,传入的参数罗列在函数调用的后面,即$NAME/$FILE
        if is_regfile "$NAME/$FILE"; then
            # 读进程文件
            echo "### 通过 redis.pid文件 方式关闭进程 ###"
            PID=$(cat "$NAME/$FILE")
        else
            # 查找进程ID
            echo "### 通过 查找进程ID 方式关闭进程 ###"
            PID=$(ps aux | grep "redis-server" | grep -v grep | awk '{print $2}')
        fi
        echo Redis server pid = $PID
        kill -9 $PID
        if [ $? -ne 0 ]; then
            echo "Redis server stop fail ..."
        else
            echo "Redis server stop success!!!"
        fi
        ;;
    status)
        ps aux | grep "redis-server" | grep -v grep > /dev/null
        if [ $? -eq 0 ];then
            echo "Redis server is running..."
        else
            echo "Redis server is not running ..."
        fi
        ;;
    *)
        echo "do nothing ..."
        ;;
esac

猜你喜欢

转载自blog.csdn.net/qq_29996285/article/details/87910519
今日推荐