Linux shell 自动安装总结

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/ManagementAndJava/article/details/80641159

本文主要针对web项目自动安装shell脚本中常用linux命令总结如下:

1. 将一条命令的执行结果赋值给一个变量:

#获取执行脚本的当前路径
zit_script_path=$(cd "$(dirname "$0")" && pwd)
#获取执行脚本的当前路径
zit_script_path=$(cd "$(dirname "$0")";pwd)

1.1 Linux 中常用的转义字符

  • 反斜杠(\) :  使反斜杠后面的一个变量变为单纯的字符串;
  • 单引号(''):  转义其中所有的变量为单纯的字符串;
  • 双引号(""): 保留其中的变量属性,不进行转义处理;
  • 反引号(``): 把其中的命令执行后返回结果。等价于 $();

1.2 Linux 下多个命令连续执行

  • 分隔符(;): 无论前面的命令执行成功与否,都会执行后一条命令;
  • 分隔符(&&): 只有前面的命令执行成功了,才会执行后一条命令;相当于 短路与
zit_path=`cd /usr/hello && pwd`
# hello不存在 zit_path等于空
  • 分隔符(||): 只有当前面的命令执行失败了,才会执行后面的命令;相当于 短路或

1.3 Linux中传递给脚本shell的参数表示

./start.sh a b c

$# 是传给脚本的参数个数 : 3

$0 是脚本本身的名字 : start.sh

$1 是传递给该shell脚本的第一个参数 : a

$2 是传递给该shell脚本的第二个参数 : b

$@ 是传给脚本的所有参数的列表 : a b c
for key in "$@"
# for key in $@ 
do
    echo $key
done
有无双引号输出结果相同: 
a
b 
c
$* 是以一个单字符串显示所有向脚本传递的参数,与位置变量不同,参数可超过9个 :    
for key2 in $*
do 
    echo $key2
done
输出结果:
a
b
c

for key2 in "$*"
do
    echo $key2
done
带引号的输出结果:
a b c 
$$ 是脚本运行的当前进程ID号 : 3324 $? 是显示最后命令的退出状态,0表示没有错误,其他表示有错误

1.4 Linux 的 dirname 和 basename

dirname -[选项] 名称
 输出名称中的目录部分,如果名称仅仅只是一个文件名,则输出".",表示当前目录
dirname /usr/install  # install 为一个目录(文件夹)
    输出:/usr 
dirname /usr/install/install.sh 
    输出:/usr/install
dirname install.sh
    输出. #.表示当前目录 无论上面的文件是否存在或者是否在当前目录
basename -[选项] 名称
   -a : 移除多个名称的目录
   -s : 移除相应的后缀名称
  表示移除名称的目录,仅保留文件名 
basename -a dir1/str dir2/str  
    输出: dir1
          dir2 
basename -a dir1/str dir2/str
    输出: dir1
basename -s .jpg dir1/str.jpg
    输出: str
basename --suffix=.jpg dir1/str.jpg
    输出: str

2. Linux shell 读取配置文件中的变量

2.1 source命令的巧妙用法

source filename 或者 . filename 通常用于重新执行刚修改的初始化文件,使之立即生效,而不必注销并重新登录。

例如,当我们修改了/etc/profile文件,并想让它立刻生效,而不用重新登录,就可以使用source命令,

source /etc/profile

source filename 只是简单地读取脚本里面的语句依次在当前shell里面执行,没有建立新的子shell。那么脚本里面所有新建、改变变量的语句都会保存在当前shell里面。因为不会建立新的子shell,变量的值都可以直接取到.

配置文件 db.ini:

db_username=root
db_port=3306
db_password=xxx

readConf.sh:

#!/bin/bash
source ./db.ini
# 会依次读取db.ini文件中的语句在当前shell中执行,而db_username=root刚好是linux中定义变量的方式,所有db_username这个变量
#会在当前的shell中生效,因此我们可以在这个shell文件中直接使用这个变量
dbUsername=${db_username}
dbPort=${db_port}
dbPassword=${db_password}
echo $dbUsername

sh filepath或者./filepath: 会重新建立一个子shell,在子shell中执行脚本里面的语句,该子shell继承父shell的环境变量,但子shell是新建的,其改变的变量不会被带回父shell,除非使用export。

2.2 awk命令

参考文档:linux awk命令详解

简单来说awk就是把文件逐行的读入,以 空格 为默认分隔符将每行切片,切开的部分再进行各种分析处理。

使用方法

awk -F'域分隔符' 'pattern + action' filenames
    -F后面跟域分割符号,默认是依空格进行分割的例如: awk -F: #依“:”进行行的域分割
    pattern: 要查找的内容,支持正则表达式,将要查找的内容用"/"进行包围;
        awk -F':' '/root/{print $6}' /etc/passwd 
        #查找到有root关键词的行,并输入第6个域的内容
    action:执行的命令

调用awk

有三种方式调用awk

1.命令行方式
awk [-F  field-separator]  '/pattern/{commands}'  input-file(s)
其中,commands 是真正awk命令,[-F域分隔符]是可选的。 input-file(s) 是待处理的文件。
在awk中,文件的每一行中,由域分隔符分开的每一项称为一个域。通常,在不指名-F域分隔符的情况下,默认的域分隔符是空格。

2.shell脚本方式
将所有的awk命令插入一个文件,并使awk程序可执行,然后awk命令解释器作为脚本的首行,一遍通过键入脚本名称来调用。
相当于shell脚本首行的:#!/bin/sh
可以换成:#!/bin/awk

3.将所有的awk命令插入一个单独文件,然后调用:
awk -f awk-script-file input-file(s)
其中,-f选项加载awk-script-file中的awk脚本,input-file(s)跟上面的是一样的。

awk内置变量

awk有许多内置变量用来设置环境信息,这些变量可以被改变,下面给出了最常用的一些变量。

ARGC               命令行参数个数
ARGV               命令行参数排列
ENVIRON            支持队列中系统环境变量的使用
FILENAME           awk浏览的文件名
FNR                浏览文件的记录数
FS                 设置输入域分隔符,等价于命令行 -F选项
NF                 浏览记录的域的个数
NR                 已读的记录数
OFS                输出域分隔符
ORS                输出记录分隔符
RS                 控制记录分隔符

 此外,$0变量是指整条记录。$1表示当前行的第一个域,$2表示当前行的第二个域,......以此类推。

 统计/etc/passwd:文件名,每行的行号,每行的列数,对应的完整行内容:

#awk  -F ':'  '{print "filename:" FILENAME ",linenumber:" NR ",columns:" NF ",linecontent:"$0}' /etc/passwd
filename:/etc/passwd,linenumber:1,columns:7,linecontent:root:x:0:0:root:/root:/bin/bash
filename:/etc/passwd,linenumber:2,columns:7,linecontent:daemon:x:1:1:daemon:/usr/sbin:/bin/sh
filename:/etc/passwd,linenumber:3,columns:7,linecontent:bin:x:2:2:bin:/bin:/bin/sh
filename:/etc/passwd,linenumber:4,columns:7,linecontent:sys:x:3:3:sys:/dev:/bin/sh

2.3 sed命令

sed 把当前处理的行存储在临时缓冲区中,称为“模式空间”(pattern space),接着用sed命令处理缓冲区中的内容,处理完成后,把缓冲区的内容送往屏幕。接着处理下一行,这样不断重复,直到文件末尾。文件内容并没有 改变,除非你使用重定向存储输出。

参考文档:

命令格式

sed [options] 'command' file(s)
sed [options] -f scriptfile file(s)
-e<script>或--expression=<script>:以选项中的指定的script来处理输入的文本文件;
-f<script文件>或--file=<script文件>:以选项中指定的script文件来处理输入的文本文件;

sed替换标记

g 表示行内全面替换。  
p 表示打印行。  
w 表示把行写入一个文件。  
x 表示互换模板块中的文本和缓冲区中的文本。  
y 表示把一个字符翻译为另外的字符(但是不用于正则表达式)
\1 子串匹配标记
& 已匹配字符串标记

sed元字符集

^ 匹配行开始,如:/^sed/匹配所有以sed开头的行。
$ 匹配行结束,如:/sed$/匹配所有以sed结尾的行。
. 匹配一个非换行符的任意字符,如:/s.d/匹配s后接一个任意字符,最后是d。
* 匹配0个或多个字符,如:/*sed/匹配所有模板是一个或多个空格后紧跟sed的行。
[] 匹配一个指定范围内的字符,如/[ss]ed/匹配sed和Sed。  
[^] 匹配一个不在指定范围内的字符,如:/[^A-RT-Z]ed/匹配不包含A-R和T-Z的一个字母开头,紧跟ed的行。
\(..\) 匹配子串,保存匹配的字符,如s/\(love\)able/\1rs,loveable被替换成lovers。
& 保存搜索字符用来替换其他字符,如s/love/**&**/,love这成**love**。
\< 匹配单词的开始,如:/\<love/匹配包含以love开头的单词的行。
\> 匹配单词的结束,如/love\>/匹配包含以love结尾的单词的行。
x\{m\} 重复字符x,m次,如:/0\{5\}/匹配包含5个0的行。
x\{m,\} 重复字符x,至少m次,如:/0\{5,\}/匹配至少有5个0的行。
x\{m,n\} 重复字符x,至少m次,不多于n次,如:/0\{5,10\}/匹配5~10个0的行。

sed用法实例

替换文本中的字符串:

sed 's/book/books/' file

-n选项p命令一起使用表示只打印那些发生替换的行:

sed -n 's/test/TEST/p' file

直接编辑文件选项-i使用后缀 /g 标记会替换每一行中的所有匹配:会匹配file文件中每一行中所有的book替换为books:

sed -i 's/book/books/g' file

以上命令中字符 / 在sed中作为定界符使用,也可以使用任意的定界符:

sed 's#test#TEXT#g' file

-d: 删除操作

删除文中的空白行

sed 's/^$/d' file
& 对应于之前所匹配到的单词:
sed 's/^192.168.0.1/&localhost/' file
192.168.0.1localhost
样式匹配子串标识位 \(.....\) -> \1

\(..\) 用于匹配子串,对于匹配到的第一个子串就标记为 \1,依此类推匹配到的第二个结果就是 \2,例如:

echo aaa BBB | sed 's/\([a-z]\+\) \([A-Z]\+\)/\2 \1/'
BBB aaa
sed表达式可以使用单引号来引用,但是如果表达式内部包含变量字符串,就需要使用双引号。

, 逗号用于选定行的范围

sed -n '/test/,/check/p' file 

所有在模板test和check所确定的范围内的行都被打印:

3. 判断一个目录是否存在,如果不存在就自动创建,并把安装文件拷入

#判断安装目录是否存在
if [ ! -d ${installDir} ]; then
	mkdir -p ${installDir}
	# 复制所有文件到安装目录
	cp -a -f ./* ${installDir}
	cd ${installDir}
else
	cp -a -f ./* ${installDir}
	cd ${installDir}
fi

3.1 Linux 判断用户的参数

3.1.1 文件测试逻辑语句

文件测试即使用指定条件来判断文件是否存在或者权限是否满足等情况的运算符,

  • -d : 测试文件是否为一个目录类型
  • -e : 测试文件是否存在
  • -f : 判断是否为一个一般文件
  • -r : 测试当前用户是否有权限读写
  • -w : 测试当前用户是否有权写入
  • -x : 测试当前用户是否有权执行

其中,对于目录文件来说,可读:表示能够读取目录内的文件列表; 可写: 表示能够在目录内新增、删除、重命名文件;可执行:表示可以进入这个目录。

常配合目录创建 删除, 复制,等操作

mkdir 命令重要参数:

- m :  为目录指定权限;

# 默认创建出来的目录为-drwxr-xr-x
mkdir -m 775 dir1 

- p :  递归创建;在创建目录过程中,如果那些目录不存在,就创建这些目录

mkdir -p totalDir/{dir1,dir2,dir3/{dir3-1,dir3-2,dir3-3}}

cp 命令重要参数 :

  • -a:此选项通常在复制目录时使用,它保留链接、文件属性,并复制目录下的所有内容。其作用等于dpR参数组合。
  • -d:复制时保留链接。
  • -f:覆盖已经存在的目标文件而不给出提示。
  • -i:与-f选项相反,在覆盖目标文件之前给出提示,要求用户确认是否覆盖,回答"y"时目标文件将被覆盖。
  • -p:除复制文件的内容外,还把修改时间和访问权限也复制到新文件中。
  • -r:若给出的源文件是一个目录文件,此时将复制该目录下所有的子目录和文件。
  • -l:不复制文件,只是生成链接文件
#将当前目录下面的所有文件复制到目标目录下,并且保持当前目录下文件的属性 -a =-d -p -r ; -f 覆盖已存在的文件不进行提示
cp -a -f ./* ${installDir}

rm 命令重要参数:

可以删除一个目录中的一个或多个文件或目录,也可以将某个目录及其下属的所有文件及其子目录均删除掉。对于链接文件,只是删除整个链接文件,而原有文件保持不变。

  • - f : 强制删除一个文件或目录,当这个目录不空时,无法删除
  • - r : 递归处理,将指定目录下的所有文件与子目录一并删除
  • - i : 询问用户是否删除
# 强制递归删除totalDir文件夹
rm -r -f totalDir

3.1.2 逻辑测试语句对测试结果进行逻辑分析

“与”(&&):表示前面的命令执行成功后,才会执行它后面的命令,

# 判断当前目录是否存在,存在就删除
[ -d ./totalDIR ] && rm -r -f ./totalDIR

“或”(||):表示当前面的命令执行失败后才会执行它后面的命令,

[ $USER != root ] || echo you must be root user!!

“非”(!):把条件测试中的判断结果取相反值,

if [ ! -d ${installDir} ]; then
	mkdir -p ${installDir}
fi

3.1.3 整数比较运输符:只是对数字的操作

  • -eq : 是否等于
  • -ne : 是否不等于
  • -gt : 是否大于
  • -lt : 是否小于
  • -le : 是否等于或小于
  • -ge : 是否大于或等于
FREE_MEN=free -m | grep Mem | awk '{print $4}'
[ FREE_MEN -lt 1024 ] && echo "Insufficient Memory"

3.1.4 字符串比较语句

  •  = : 比较两个字符串是否相等
  • !=:比较两个字符串的内容是否不同
  • -z : 判断字符串内容是否为空
[ $LANG != "en.US" ]

4. 将查到到符合条件的文件放入一个数组,然后遍历这个数组对文件进行一一操作

#根据数据库类型删除相应的数据库驱动jar包
if [ "$dbType" == "MSSQL2008" ]; then
        # 声明一个数组
        declare -a MSQL2008_ARR
	MSSQL2008_ARR=$(find ./server -name sqljdbc2005.jar)
	if [ ${#MSSQL2008_ARR[@]} -gt 0 ]; then
		for i in ${MSSQL2008_ARR[@]}; do
			rm -f $i
		done
	fi

4.1 对数组的操作;

4.1.1 声明一个数组:

数组的脚标从0开始;

直接赋值:

array[0]=”Zero” array[1]=”One” array[2]=”Two”

declare声明:

declare -a arrayName  #arrayName被当作数组名

小括号加空格定义数组:

arrayName=( value1 value2 value3 ... )

双引号加空格定义数组:

array=”Zero One Two”

混合法:

array=([0]=”Zero” [1]=”One” [2]=”Two”)

4.1.2 数组操作

 获取数组长度和遍历数组:

    
# 取得数组元素的个数
length=${#array_name[@]}
    # 遍历数组
    for data in ${array_name[@]}  
    do  
        echo ${data}  
    done      
# 或者
length=${#array_name[*]}
    # 遍历数组
    for(( i=0; i<${length}; i++ )) 
    do 
        echo ${array[i]}; 
    done
# 取得数组 单个元素 的长度
lengthn=${#array_name[n]}

数组赋值和删除数组

a=(1 2 3 4 5 6 7 8)
a[1]=100
echo ${a[*]} # 1 100 2 3 4 5 6 7 8
a[11]=200
${a[*]} # 1 100 2 3 4 5 6 7 8 200 
如果下标不存在就直接添加一个新的元素在末尾

#删除元素
unset array_name #删除数组
unset array_name[i] #删除第i个脚标的元素

数组切片与替换

a=(1 2 3 4 5 6 7 8)
echo ${a[@]:0:3} #[ )
    1 2 3
c=(${a[@]:1:4})
echo ${c[*]} 
    2 3 4 5
# 数组元素替换 
a=(1 2 3 4 5 6 7 8)
echo ${a[@]/3/100} # 将数组中的3 替换成100
# 输出:1 2 100 4 5 6 7 8
echo ${a[*]}
# 输出:1 2 3 4 5 6 7 8 #原数组的值并没有发生变化

a=(${a[@]/3/100})
echo ${a[@]}
# 输出:1 2 100 4 5 6 7 8 #从新赋值给一个新的数组 替换掉源数组的值


4.2 cat file 返回一个数组

vim user.txt
    zhangsan
    lisi
    wangwu
    zhaoliu
# cat 出来的内容直接作为一个数组
NAME_ARR=$(cat ./user.txt)
for user in NAME_ARR
do
    echo $NAME_ARR
done

4.3 find 命令

find path -iname fileName*

#查找当前目录下所有dir开头的脚本文件(忽略大小写)
find . -iname dir*.sh

4.4 grep命令

参考文档 Linux grep 命令详解

grep [-cinv] [--color=auto] '搜寻字符串' filename1 filename2 

要搜寻的字符中中可以使用正则表达式 用单引号包裹 
filename 是文件名,不能为目录

选项与参数:
-c :计算找到 '搜寻字符串' 的次数
-i :忽略大小写的不同,所以大小写视为相同
-n :顺便输出行号
-v :反向选择,亦即显示出没有 '搜寻字符串' 内容的那一行!
--color=auto :可以将找到的关键词部分加上颜色的显示!

示例:
grep -c -n -i 'root' /etc/passwd
cat /etc/passwd | grep -c -n -i 'root'

# 递归搜查 
grep ‘#!/bin/*’ *           #在当前目录下的文件搜索带'#!/bin/*'行的文件
grep -r '#!/bin/*' *        #在当前目录及其子目录下搜索'#!/bin/*'行的文件
grep -l -r ‘#!/bin/*’ *     #在当前目录及其子目录下搜索'#!/bin/*'行的文件,但是不显示匹配的行,只显示匹配的文件

5. 验证远程服务器是否可以ping同,并根据结果做相应的处理

#验证数据库服务器地址是否可以ping成功
ping -c 1 $dbIP > /dev/null 2>&1
if [ $? -eq 0 ]; then
	echo ... ping $dbIP successfully
else
	echo ... ping $dbIP defeated
	exit 1
fi

5.1 ping 命令

在shell 脚本中ping命令一定要但参数 -c (接收的次数)因为linux 的ping命令不会自动停止

5.2 linux 中特殊变量 $0 $1 $2 ... $n $* $@  $# $$ $?

  • $0  :  当前脚本的文件名  
  • $n  :  传递给脚本或函数的参数。n 表示第几个参数。例如,第一个参数是$1,第二个参数是$2。  
  • $# : 传递给脚本或函数的参数个数。  
  • $*  : 传递给脚本或函数的 所有参数 。  
  • $@:传递给脚本或函数的所有参数。被双引号(" ")包含时,与 $* 稍有不同。  
  • $?  :上个命令的退出状态,或函数的返回值。执行成功会返回 0,失败返回 非0。  
  • $$ :当前Shell进程ID。对于 Shell 脚本,就是这些脚本所在的进程ID。 
$* 和 $@ 的区别  
       $* 和 $@ 都表示传递给函数或脚本的所有参数,不被双引号(" ")包含时,都以"$1" "$2" … "$n" 的形式输出所有参数。 但是当它们被双引号(" ")包含时,"$*" 会将所有的参数作为一个整体,以"$1 $2 … $n"的形式输出所有参数;"$@" 会将各个参数分开,以"$1" "$2" … "$n" 的形式输出所有参数。 
./test.sh "a" "b" "c" "d"
print each param from "$*"
    a b c d
print each param from "$@"
a
b
c
d
说明:双引号包含时,"$*"的参数被当做一个整体,而"$@"还是遍历每一个参数

5.3 重定向问题

参考文档: linux中的重定向问题

简而言之,输入重定向是指把文件导入到命令中, 输出重定向是指把原本要输出到屏幕的数据信息写入到指定的文件。而输出重定向又分为标准输出重定向和错误输出重定向

5.3.1 重定向符号

  • 标准输入重定向(STDIN 文件描述为 0):默认从键盘输入,也可以重其它文件输入或命令输入,使用的方式为 <

   重定向符号:<

wc -l < reademe.txt
  标准输入重定向符号: << 分界符   (从标准输入中(键盘)读入,直到遇见分界符才停止)
wc -m << BYE
> hello
> world
>BYE
12
  • 标准输出重定向(STDOUT 文件描述为 1):默认输出到屏幕,使用的方式为 1>

    命令 > 文件  : 将标准输出重定向到一个文件中 (清空原来文件的数据)

    命令 >> 文件:将标准输出重定向到一个文件中(追加到原有内容的后面)   

  • 错误输出重定向(STDERR 文件描述为 2):默认输出到屏幕, 使用的方式为 2>

    命令 2> 文件  : 将错误输出重定向到一个文件中 (清空原来文件的数据)   

    命令 >> 文件 : 将错误输出重定向到一个文件中(追加到原有内容的后面)   

组合形式:

    命令 >> 文件 2 > &1

    命令 &>>文件

   上面两个命令等价: 将标准输出与错误输出共同写入到文件中(追加到源文件的后面)

5.3.2 linux的“黑洞”文件

ls -al 1> list.txt 2> /dev/null
将显示的数据,正确的输出到 list.txt ;错误的数据则予以丢弃! /dev/null ,可以说成是黑洞装置。为空,即不保存。


6. shell中调用java命令,并接受返回值

# 执行java 命令并将返回值输入到变量

result=$(java -jar ./install_linux.jar)

if [ ${result} = "true" ]; then
	echo ... execute dbscripts finished
	#删除数据库脚本文件
	rm -rf ./server/dbscript
else
	echo ... execute dbscripts have met a error. please check the dbscript or network
	exit 1
fi
注意在 java代码中必须要输出(System.out.println("true")),其实它还是根据输出来判断的;


7. Linux中tomcat开机自启动脚本

参考文献: Linux tomcat开机自启动

第一步:在/etc/init.d文件下建立启动shell脚本, 并编写自启动脚本

vi /etc/init.d/tomcat

第二步: 设置脚本权限   

chmod 755 tomcat

第三步:将这个shell文件挂载到/etc/rc2.d下

/etc/rc.d/rcx.d/下的文件均为符号链接,最终绝大部分都是都是链接到/etc/rc.d/init.d下面。

    linux的/etc/rcX.d/目录中的数字代表开机启动时不同的run level,也就是启动的顺序,用ln命令将tomcat的链接链过去:rcX.d目录下的命名规则是很有讲究的,根据不同需要可能是S开头,也可能是K开头,之后的数字代表他们的启动顺序; linux在加载过程中加载到init程序时,会去读/etc/rc.d/rcx.d/下的文件,均为符号链接,最终绝大部分都是都是链接到/etc/rc.d/init.d下面 ,我们可以知道,/etc/rc.d/init.d目录下面的都是开启启动脚本文件,用来启动相应的程序
ln -s /etc/init.d/tomcat /etc/rc2.d/S16tomcat

第四步:设置脚本开机自启动

chkconfig --add /etc/init.d/tomcat

第五步:使用linux系统服务命令 service 管理tomcat服务

service tomcat status # 查看服务状态    
service tomcat start  # 启动服务
service tomcat stop   # 停止服务
service tomcat restart  #重启服务

7.1 编写tomcat自启动脚本

#!/bin/sh
# chkconfig: 345 99 10
# description: Auto-starts tomcat
# /etc/init.d/tomcatd
# Tomcat auto-start
# Source function library.
#. /etc/init.d/functions
# source networking configuration.
#. /etc/sysconfig/network

RETVAL=0

#获取jdk的绝对路径
java_relative_home=/usr/zlits_dms/jdk
export JAVA_HOME=$(readlink -f ${java_relative_home})
export JRE_HOME=$(readlink -f ${java_relative_home}/jre)
tomcat_relative_home=/usr/zlits_dms/server/tomcat
export CATALINA_HOME=$(readlink -f ${tomcat_relative_home})
#服务名称
service_name=tomcat

start()
{
        if [ -f $CATALINA_HOME/bin/startup.sh ]; then
            echo $"Starting Tomcat"
                $CATALINA_HOME/bin/startup.sh
            RETVAL=$?
            echo " OK"
            return $RETVAL
        fi
}
stop()
{
        if [ -f $CATALINA_HOME/bin/shutdown.sh ]; then
            echo $"Stopping Tomcat"
                $CATALINA_HOME/bin/shutdown.sh
            RETVAL=$?
            sleep 1
            ps -fwwu root | grep tomcat|grep -v grep | grep -v PID | awk '{print $2}'|xargs kill -9
            echo " OK"
            # [ $RETVAL -eq 0 ] && rm -f /var/lock/...
            return $RETVAL
        fi
}
status()
{
    svrs=`ps aux | grep root | grep tomcat | grep -v grep | grep -v status | wc -l`
    if [ $svrs -gt 0 ]; then
        echo -e "\033[1;32;40m${service_name} is running now!\033[0m"
    else
        echo -e "\033[1;31;40m${service_name} is not running now!\033[0m"
    fi
}

case "$1" in
 start) 
        start
        ;;
 stop)  
        stop
        ;;
 status)  
        status
        ;;                                           
 restart)
         echo $"Restaring Tomcat"
         $0 stop
         sleep 1
         $0 start
         ;;
 *)
        echo $"Usage: $0 {start|stop|restart|status}"
        exit 1
        ;;
esac
exit $RETVAL

7.1.1 shell case 条件测试语句形式和函数调用

case 变量值 in                case 输入的字符 in
模式1)                        [a-z]|[A-Z])
    命令序列 1                    提示为字母
    ;;                           ;;
模式2)                        [0-9])
    命令序列 2                    提示为数组
    ;;                           ;;
*)                            *)
    默认命令序列                   默认命令
esac                          esac

由于 shell script 的执行方式由上向下、由左向右,因此在shell script当中的function的设置一定要在程序的最前面,这样才能够在执行的时候找到可用的程序段;

function fname() {
    代码块;
}
fanme # 调用函数

7.1.2 一个shell脚本中调用另一个shell脚本的方式

参考文献:跨shell脚本的调用

先来说一下主要以下有几种方式及调用方式:

  • fork: 如果脚本有执行权限的话,path/foo.sh。如果没有,sh path/foo.sh
  • exec: exec path/foo.sh
  • source: source path/foo.sh  等价于 . /path/foo.sh

fork

fork 是最普通的, 就是直接在脚本里面用 path/foo.sh 来调用
foo.sh 这个脚本,比如如果是 foo.sh 在当前目录下,就是 ./foo.sh。运行的时候 terminal 会新开一个子 Shell 执行脚本 foo.sh,子 Shell 执行的时候, 父 Shell 还在。子 Shell 执行完毕后返回父 Shell。 子 Shell 从父 Shell 继承环境变量,但是子 Shell 中的环境变量不会带回父 Shell。

exec

execfork 不同,不需要新开一个子 Shell 来执行被调用的脚本. 被调用的脚本与父脚本在同一个 Shell 内执行。但是使用 exec 调用一个新脚本以后, 父脚本中 exec 行之后的内容就不会再执行了。这是 execsource 的区别.

source

source 操作也成为 . 操作;

fork 的区别是不新开一个子 Shell 来执行被调用的脚本,而是在同一个 Shell 中执行. 所以被调用的脚本中声明的变量和环境变量, 都可以在主脚本中进行获取和使用。source方式的结果是两者在同一进程里运行。该方式相当于把两个脚本先合并再运行。

Command Explanation
fork 新开一个子 Shell 执行,子 Shell 可以从父 Shell 继承环境变量,但是子 Shell 中的环境变量不会带回给父 Shell。
exec 在同一个 Shell 内执行,但是父脚本中 exec 行之后的内容就不会再执行了
source 在同一个 Shell 中执行,在被调用的脚本中声明的变量和环境变量, 都可以在主脚本中进行获取和使用,相当于合并两个脚本在执行。

7.1.3 ps命令 xargs 命令 kill 命令

#原文命令
ps -fwwu root | grep tomcat|grep -v grep | grep -v PID | awk '{print $2}'|xargs kill -9

#自己命令
ps -aux | grep root | grep tomcat | grep -v grep |awk '{pirnt $2}' | xargs kill -9

#命令 
ps -aux 
#输出格式
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
  USER:该 process 属于那个使用者账号的 
  PID :该 process 的号码 
  %CPU:该 process 使用掉的 CPU 资源百分比 
  %MEM:该 process 所占用的物理内存百分比 
  VSZ :该 process 使用掉的虚拟内存量 (Kbytes) 
  RSS :该 process 占用的固定的内存量 (Kbytes) 
  TTY :该 process 是在那个终端机上面运作,若与终端机无关,则显示 ?
  STAT:该程序目前的状态,主要的状态有 
  R :该程序目前正在运作,或者是可被运作 
  S :该程序目前正在睡眠当中 (可说是 idle 状态),但可被某些讯号 signal) 唤醒。 
  T :该程序目前正在侦测或者是停止了 
  Z :该程序应该已经终止,但是其父程序却无法正常的终止他,造成 zombie (疆尸) 程序的状态 
  START:该 process 被触发启动的时间 
  TIME :该 process 实际使用 CPU 运作的时间 
  COMMAND:该程序的实际指令

xargs 命令

参考文献:xargs详解

xargs能够处理管道或者stdin并将其转换成特定命令的命令参数。xargs也可以将单行或多行文本输入转换为其他格式,例如多行变单行,单行变多行。xargs的默认命令是echo,空格是默认定界符。这意味着通过管道传递给xargs的输入将会包含换行和空白,不过通过xargs的处理,换行和空白将被空格取代。xargs是构建单行命令的重要组件之一

cat test.txt

a b c d e f g
h i j k l m n
o p q
r s t
u v w x y z
cat test.txt | xargs

a b c d e f g h i j k l m n o p q r s t u v w x y z
echo '--help' | xargs cat
# echo '--help' | xargs cat 等价于 cat --help ,就是xargs将其接受的字符串 --help 做成cat的一个命令参数来运行cat命令,
#同样  echo 'test.c test.cpp' | xargs cat 等价于 cat test.c test.cpp 此时会将test.c和test.cpp的内容都显示出来。

kill 命令

kill -option PID
 -option
    -l 信号([ 2 中断 同Ctrl + c ] [3 退出 同Ctrl+\] [9 无条件强行终止] [19 暂停])

    只有第9种信号(SIGKILL)才可以无条件终止进程,其他信号进程都有权利忽略。  

7.1.4 Shell中各种括号的详解

参考文档:shell中的各种括号详解

小括号 () : 

    命令组。括号中的命令将会新开一个子shell顺序执行所以括号中的变量不能够被脚本余下的部分使用。括号中多个命令之间用分号(或&&, 主要区别)隔开,最后一个命令可以没有分号,各命令和括号之间不必有空格。

    命令替换。 等同于两个反单引号,`commond`。

    声明数组。 declare -a array_name; array_name=( 1 2 3 );

双小括号 (()) :

    (1)整数扩展。这种扩展计算是整数型的计算,不支持浮点型。((exp))结构扩展并计算一个算术表达式的值,如

result=$((5-3))

    注释:对于本小节开头部分引用的文献中整数扩展部分所说的,当表达式的值为非零则。。。自己可能没有理解博主意思,感觉不对,没有引入到本文中

    (2)常用于算术运算比较。双括号中的变量可以不使用$符号前缀。括号内支持多个表达式用逗号分开。 只要括号中的表达式符合C语言运算规则,

  • 比如可以直接使用for((i=0;i<5;i++)), 如果不使用双括号, 则为for i in `seq 0 4`或者for i in {0..4}。
  • 再如可以直接使用if (($i<5)), 如果不使用双括号, 则为if [ $i -lt 5 ]。

(3)单纯用 (( )) 也可重定义变量值,比如 a=5; ((a++)) 可将 $a 重定义为6

中括号 [] :

    Test和[]具有相同的功效(判断符号);

    文件:-e -f -d -b -L

    权限: -w -r -x -u -g -k -s

    两个文件比较:-nt  -ot -ef

    整数判断: -eq -ne -gt -lt -ge -le

    字符串判断: -z -n = !=

    多重条件判断: -a -0 !

if [ -r file1 -a -x file1 ]; then
    echo file1 has r x right;
fi
if test -r file1 -a -x file1 ; then
    echo file1 has r x right;
fi 

双中括号 [[]] :

    使用[[ ... ]]条件判断结构,而不是[ ... ],能够防止脚本中的许多逻辑错误。比如,&&、||、<和> 操作符能够正常存在于[[ ]]条件判断结构中,但是如果出现在[ ]结构中的话,会报错。比如可以直接使用if [[ $a != 1 && $a != 2 ]], 如果不适用双括号, 则为if [ $a -ne 1] && [ $a != 2 ]或者if [ $a -ne 1 -a $a != 2 ]。

大括号 {} :

    大括号拓展。(通配(globbing))将对大括号中的文件名做扩展。在大括号中,不允许有空白,除非这个空白被引用或转义。

# ls {ex1,ex2}.sh 
ex1.sh ex2.sh 
# ls {ex{1..3},ex4}.sh 
ex1.sh ex2.sh ex3.sh ex4.sh 
# ls {ex[1-3],ex4}.sh 
ex1.sh ex2.sh ex3.sh ex4.sh

     (2)代码块,又被称为内部组,这个结构事实上创建了一个匿名函数 。与小括号中的命令不同,大括号内的命令不会新开一个子shell运行,即脚本余下部分仍可使用括号内变量。括号内的命令间用分号隔开,最后一个也必须有分号。{}的第一个命令和左括号之间必须要有一个空格。

(cmd1;cmd2;cmd3)和{ cmd1;cmd2;cmd3}

    (1)单小括号,(cmd1;cmd2;cmd3) 新开一个子shell顺序执行命令cmd1,cmd2,cmd3, 各命令之间用分号隔开, 最后一个命令后可以没有分号。

    (2)单大括号,{ cmd1;cmd2;cmd3;} 在当前shell顺序执行命令cmd1,cmd2,cmd3, 各命令之间用分号隔开, 最后一个命令后必须有分号, 第一条命令和左括号之间必须用空格隔开。

特殊替换:

形式 说明
${var} 变量本来的值
${var:-word} 如果变量 var 为空或已被删除(unset),那么返回 word,但不改变 var 的值。
${var:=word} 如果变量 var 为空或已被删除(unset),那么返回 word,并将 var 的值设置为 word。
${var:?message} 如果变量 var 为空或已被删除(unset),那么将消息 message 送到标准错误输出,可以用来检测变量 var 是否可以被正常赋值。
若此替换出现在Shell脚本中,那么脚本将停止运行。
${var:+word} 如果变量 var 被定义,那么返回 word,但不改变 var 的值。

模式匹配替换:

${var%pattern},${var%%pattern},${var#pattern},${var##pattern}
${var%pattern}
#shell在variable中查找,看它是否依给的模式pattern结尾,如果是,就从命令行把variable中的内容 去掉 右边最短 的匹配模式 
${var%%pattern}
#shell在variable中查找,看它是否依给的模式pattern结尾,如果是,就从命令行把variable中的内容 去掉 右边最长 的匹配模式
${var#pattern}
#shell在variable中查找,看它是否依给的模式pattern开始,如果是,就从命令行把variable中的内容 去掉 左边最短 的匹配模式
${var##pattern}
#shell在variable中查找,看它是否依给的模式pattern开始,如果是,就从命令行把variable中的内容 去掉 左边最长 的匹配模式

这四种模式中都不会改变variable的值,其中,只有在pattern中使用了*匹配符号时,%和%%,#和##才有区别。结构中的pattern支持通配符,*表示零个或多个任意字符,?表示仅与一个任意字符匹配,[...]表示匹配中括号里面的字符,[!...]表示不匹配中括号里面的字符

str=/home/guest/shell/hello.sh
${str#/*/} ## guest/shell/hello.sh
${str##/*/} ## hello.sh

字符串提取和替换:

${var:num},${var:num1:num2},${var/pattern1/pattern2},${var//pattern1/pattern2}
${var:num}
#shell在var中提取第num个字符到末尾的所有字符。若num为正数,从左边0处开始;
#若num为负数,从右边开始提取字串,提起num个字符串,形式:${var:-2}或${var:(-2)}。
#例如:
var=1234567890
echo ${var:4} #567890
echo ${var:-4} #0987
${var:num1:num2}
# num1是位置,num2是长度。表示从$var字符串的第num1个位置开始提取长度为num2的子串。
# num2不能为负数,当大于字符串长度时,取最大长度。
var=1234567890
echo ${var:3:3}  #456
echo ${var:3:13} #4567890
${var/pattern1/pattern2}
# 表示将var字符串的第一个匹配的pattern1替换为另一个pattern2。
var=1234563337890
echo ${var/3/a}  #12a4563337890
${var//pattern1/pattern2}
# 表示将var字符串的匹配到的pattern1全部替换为另一个pattern2。
var=1234563337890
echo ${var//3/a}  #12a456aaa7890

7.2 chkconfig 命令

参考文档:Linux chkconfig命令











猜你喜欢

转载自blog.csdn.net/ManagementAndJava/article/details/80641159