加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

shell编程基础

发布时间:2020-12-15 09:14:06 所属栏目:安全 来源:网络整理
导读:1 变量 [root@zab ~]# name=zhang [root@zab ~]# echo $name zhang [root@zab ~]# vim zh.sh #!/bin/bash echo "$name" name=wang echo "zh.sh:name=$name" ~ [root@zab ~]# bash zh.sh zh.sh:name=wang [root@zab ~]# echo $name zhang [root@zab ~]# sourc

1变量

[root@zab ~]# name=zhang

[root@zab ~]# echo $name

zhang

[root@zab ~]# vim zh.sh

#!/bin/bash

echo "$name"

name=wang

echo "zh.sh:name=$name"

~

[root@zab ~]# bash zh.sh

zh.sh:name=wang

[root@zab ~]# echo $name

zhang

[root@zab ~]# source zh.sh = . zh.sh

zh.sh:name=wang

[root@zab ~]# echo $name

wang

程序执行用bash不需要执行权限 。执行需要执行权限以及程序的路径执行。如./zh.sh 在当前目录下执行 /root/zh.sh 绝对路径执行 source会影响操作环境。

bash.会开启子进程 source不会开启子进程.

显示当前进程编号echo $$

显示进程关系 pstree -p

[root@zab ~]# num1=zhang

[root@zab ~]# num2=$num1 ---- num1指向的数据地址zhang num2也指向地址zhang 并不是num2指向num1

[root@zab ~]# echo $num1

zhang

[root@zab ~]# echo $num2

zhang

[root@zab ~]# num1=wang ---- num1的指向地址由zhang变为wang

[root@zab ~]# echo $num1

wang

[root@zab ~]# echo $num2 ---- num2的指向地址还是zhang

Zhang

[root@zab ~]# unset num1 num2 ----当脚本执行完后,需unset取消变量定义 如果取消环境变量。会影响调用该变量的进程。

2变量种类

*本地变量:生效范围当前shell进程 在脚本下定义变量为本地变量 不能影响脚本里的脚本

[root@zab ~]# vim f1.sh

#!/bin/bash

n="su1"

echo "f1.sh:n=$n"

./f2.sh 调用f2.sh 要指明路径

~

[root@zab ~]# vim f2.sh

#!/bin/bash

echo "f2.sh:n=$n"

s="su2"

echo "f2.sh:s=$s"

~

[root@zab ~]# chmod +x f2.sh f2.sh赋予执行权限

[root@zab ~]# bash f1.sh

f1.sh:n=su1

f2.sh:n= 未显示

f2.sh:s=su2

[root@zab ~]# bash -x f1.sh 进行调试

+ n=su1

+ echo f1.sh:n=su1

f1.sh:n=su1

+ ./f2.sh

f2.sh:n= 变量n为本地变量只对f1.sh生效 未对f2.sh生效

f2.sh:s=su2

注意{ ;空格}


在操作环境终端下输入定义name 变量赋值 name变量影响子进程b.sh 以及b.sh脚本中脚本f1.sh


*变量赋值:(1) 可以是直接字串; name="root" (2) 变量引用:name="$USER" (3) 命令引用:name=`COMMAND` name=$(COMMAND)

(2)变量引用:${name} $name

[root@zab ~]# name=`cat /etc/fstab`

[root@zab ~]# echo $name

# # /etc/fstab # Created by anaconda on Tue Jul 11 21:48:40 2017 # # Accessible filesystems,by reference,are maintained under '/dev/disk'

[root@zab ~]# echo "$name"

#

# /etc/fstab

# Created by anaconda on Tue Jul 11 21:48:40 2017

#

# Accessible filesystems,are maintained under '/dev/disk'

"$name" $name两者区别

如果name=命令

要执行命令 $name

3.环境变量:生效范围为当前shell进程以及子进程 脚本下定义环境变量 会影响脚本里脚本

[root@zab ~]# vim f1.sh

#!/bin/bash

n="su1"

export n n为环境变量

echo "f1.sh:n=$n"

./f2.sh 调用f2.sh

echo "f1.sh:n=$n"

[root@zab ~]# vim f2.sh

#!/bin/bash

echo "f2.sh:n=$n"

s="su2"

echo "f2.sh:s=$s"

n="su3" 环境变量n重新赋值su3

echo "f2.sh:n=$n"

./f3.sh

[root@zab ~]# vim f3.sh

#!/bin/bash

echo "f3.sh:n=$n"

[root@zab ~]# chmod +x f3.sh

[root@zab ~]# bash f1.sh

f1.sh:n=su1 定义n为环境变量 值为su1

f2.sh:n=su1 环境变量f2.shnsu1

f2.sh:s=su2 f2.sh并给S赋值 并重新定义环境变量n 赋值为su3

f2.sh:n=su3 n值为su3

f3.sh:n=su3 f2.sh中调用f3.sh 因为环境变量n重新定义su3

f1.sh:n=su1 返回f1.sh n的值为su1

可以发现环境变量会影响当前shell进程以及后续的子进程,但不会影响向上的父进程。

变量声明、赋值: export name=VALUE declare -x name=VALUE

变量引用:$name,${name}

*脚本调试:

检测脚本中的语法错误bash -n *.sh

调试执行 bash -x *.sh

*脚本不能识别别名

只读变量:只能声明,但不能修改和删除 ü

声明只读变量: readonly name declare -r name ü

查看只读变量: readonly p

在脚本中set -- 清空所有位置变量

unset name 取消变量

*只读变量

[root@zab ~]# name=zhang;file=d.log;(age=20;echo $age;echo $name;name=wang;num=two);echo $name;echo $num;echo $file

20

zhang

zhang

d.log

括号内变量只影响括号内 括号外的变量能影响括号内 括号相当于开启子shell进程

[root@zab ~]# umask

0022

[root@zab ~]# (umask 777;touch f1)

[root@zab ~]# ll f1

----------. 1 root root 0 Jul 27 18:24 f1 umask777

[root@zab ~]# touch f3

[root@zab ~]# ll f3 umask022

-rw-r--r--. 1 root root 0 Jul 27 18:25 f3 umask在括号内定义,只影响括号内;括号外不影响,umask为原值

*位置变量:在脚本代码中调用通过命令行传递给脚本的参数

$1,$2,...:对应第1、第2等参数,shift [n]换位置

$0: 命令本身

$*: 传递给脚本的所有参数,全部参数合为一个字符串

$@: 传递给脚本的所有参数,每个参数为独立字符串

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

$@ $* 只在被双引号包起来的时候才会有差异

set -- 清空所有位置变量

[root@zab ~]# vim f1.sh {a..m}

#!/bin/bash

echo "1st arg is $1"

echo "2st arg is $2"

echo "10st arg is ${10}"

echo "All args are $*"

echo "All args are $@"

echo "$0"

echo "$#"

~

[root@zab ~]# bash f1.sh {a..m}

1st arg is a

2st arg is b

10st arg is j

All args are a b c d e f g h i j k l m

All args are a b c d e f g h i j k l m

f1.sh

13

[root@zab ~]# bash f1.sh {a..m}

#!/bin/bash

echo "1st arg is $1"

echo "All args are $@"

shift 2

echo "shift 2"

echo "1st arg is $1"

echo "All args are $@"

~

[root@zab ~]# bash f1.sh {a..m}

1st arg is a

All args are a b c d e f g h i j k l m

shift 2 shift [n]换位置

1st arg is c 第一个参数变为c

All args are c d e f g h i j k l m

[root@zab ~]# vim f2.sh

#!/bin/bash

echo "$@"

./f3.sh "$@" 创建f3.sh 需指明路径

./f4.sh "$*" 同上

[root@zab ~]# vim f3.sh

#!/bin/bash

echo "$1"

[root@zab ~]# vim f4.sh

#!/bin/bash

echo "$1"

[root@zab ~]# chmod +x f3.sh

[root@zab ~]# chmod +x f4.sh

[root@zab ~]# bash f2.sh {a..m}

a b c d e f g h i j k l m

a

a b c d e f g h i j k l m

[root@zab ~]# bash -x f2.sh {a..m}

+ echo a b c d e f g h i j k l m

a b c d e f g h i j k l m

+ ./f3.sh a b c d e f g h i j k l m $@

a $1

+ ./f4.sh 'a b c d e f g h i j k l m' $*

a b c d e f g h i j k l m $1

$*$@区别

*自动生成脚本前描述信息

[root@zab ~]# vim scipt.sh

#!/bin/bash

cat>$1<<eof

#!/bin/bash

######################

#auther:71

#creat-time:`date +%F`

#filename:`basename $1`

######################

eof

vim + $1

chmod +x $1

~

~

[root@zab ~]# bash scipt.sh zab.sh

#!/bin/bash

######################

#auther:71

#creat-time:2017-07-27

#filename:zab.sh

######################

~

~

退出状态

进程使用退出状态来报告成功或失败

? 0 代表成功,1255代表失败

? $? 变量保存最近的命令退出状态

vbash自定义退出状态码

exit [n]:自定义退出状态码 用于编写脚本执行命令,给命令不同的状态码,看命令是否成功

注意:脚本中一旦遇到exit命令,脚本会立即终止;终止退出 状态取决于exit命令后面的数字

注意:如果未给脚本指定退出状态码,整个脚本的退出状态码 取决于脚本中执行的最后一条命令的状态码

exit退出 在字符界面当前终端 在脚本里退出当前进程

[root@centos7 ~]#cat b.sh

#!/bin/bash

cmd

(exit 100) ()号表示开启的子进程 exit退出当前子进程

hostname

[root@centos7 ~]#bash b.sh

b.sh: line 2: cmd: command not found

centos7.64 继续执行

#!/bin/bash

cmd

exit 100 退出当前进程

hostname 不执行

[root@centos7 ~]#bash b.sh

b.sh: line 2: cmd: command not found

[root@centos7 ~]#echo $?

100

算术运算

vbash中的算术运算:help let +,-,*,/,%取模(取余),**(乘方) 数字 $[number]

实现算术运算:

(1) let var=算术表达式 let c=a+b echo $c

(2) var=$[算术表达式]

(3) var=$((算术表达式)) $((a-b))

(4) var=$(expr arg1 arg2 arg3 ...) expr 1 + 2 命令 1 + 2为参数 需要空格 expr 0 + $num 可用于判断num是不是非0的整数

5) declare i var = 数值

(6) echo ‘算术表达式’ | bc v

乘法符号有些场景中需要转义,如* 为(*

bash有内建的随机数生成器:$RANDOM0-32767 echo $[$RANDOM%50] 0-49之间随机

echo $SHLVL 当前进程嵌套深度pstree -p 查看

[root@centos7 ~]#i=10

[root@centos7 ~]#let j=i++

[root@centos7 ~]#echo $j

10

[root@centos7 ~]#echo $i

11

[root@centos7 ~]#unset i

[root@centos7 ~]#i=10

[root@centos7 ~]#let j=++i

[root@centos7 ~]#echo $j

11

[root@centos7 ~]#echo $i

11

注意如下

[root@centos7 ~]#unset k

[root@centos7 ~]#let k=0

[root@centos7 ~]#let k++ k0

[root@centos7 ~]#echo $?

1

[root@centos7 ~]#unset k

[root@centos7 ~]#let k=0

[root@centos7 ~]#let ++k k1

[root@centos7 ~]#echo $?

0

exit状态 最后一个参数为0,将返回1

[root@centos7 ~]#let k+=6

[root@centos7 ~]#echo $k

7

[root@centos7 ~]#let k+=6 = k=k+6

[root@centos7 ~]#echo $k

13

条件测试 用于两个参数进行判断

专用的测试表达式需要由测试命令辅助完成测试过程

? [ EXPRESSION ]

?[[ EXPRESSION ]] 用于正则表达式

注意:EXPRESSION前后必须有空白字符

[]内是字符串、数值、文件测试 单条命令判断不需要[]中括号

表达式查看test man帮助

注意如下

[root@centos7 ~]#var=' '

[root@centos7 ~]#[ $var ] && echo true

[root@centos7 ~]#echo $?

1 字符为空 判断为假

[root@centos7 ~]#[ 0 ] && echo true

true

1.字符串测试

= 等于则为真

变量比较用到的操作数需加引号

[ "$a" = "wang" ] 或者[ x$a == x"wang" ]前面加字符防止$a为空而报错

格式的例子:

[ "abc" = "abc" ] && echo "Strings are equal"

!= 是否不等于,不相等为真

=~ 左侧字符串是否能够被右侧的PATTERN所匹配

注意: 此表达式一般用于[[ ]]中;扩展的正则表达式

[[ $a =~ &;[Yy]|([Yy][Ee][sS])$ ]] && echo "hello" ||echo "fk"

-z "STRING 字符串是否为空,空为真,不空为假 [ ! -z string ] 同于 [ -n srting ]

-n "STRING 字符串是否不空,不空为真,空为假

实例演示:

num1="ru1noob"
num2="runoob"
if
[ $num1 = $num2 ]
then
echo '
两个字符串相等!'
else
echo '
两个字符串不相等!'
fi

输出结果:

两个字符串不相等!

2.数值测试

-eq 等于则为真

-le小于等于则为真

-lt小于则为真

-ge大于等于则为真

-gt大于则为真

实例演示:

num1=100
num2=100
if
[ ${num1} -eq ${num2} ]
then
echo '
两个数相等!'
else
echo '
两个数不相等!'
fi

输出结果:

两个数相等!

代码中的 [] 执行基本的算数运算,如:

#!/bin/bash

a=5
b=6

result=$[a+b] # 注意等号两边不能有空格
echo "result
为: $result"

结果为:

result 为: 11

Bash的文件权限测试

3.文件测试

文件存在测试:

-e 文件名 如果文件存在则为真

-s 文件名 如果文件存在且内容非空则为真

文件类型测试:


-d 文件名 如果文件存在且为目录则为真

-f 文件名 如果文件存在且为普通文件则为真

-c 文件名 如果文件存在且为字符型特殊文件则为真

-b 文件名 如果文件存在且为块特殊文件则为真

文件是否打开:

-t fd: fd表示文件描述符是否已经打开且与某终端相关

-N FILE:文件自动上一次被读取之后是否被修改过

-O FILE:当前有效用户是否为文件属主 文件所有者

-G FILE:当前有效用户是否为文件属组 文件所属组

文件权限测试: 实际权限

-r FILE:是否存在且可读

-w FILE: 是否存在且可写

-x FILE: 是否存在且可执行

文件特殊权限测试:

-u FILE:是否存在且拥有suid权限

-g FILE:是否存在且拥有sgid权限

-k FILE:是否存在且拥有sticky权限

双目测试:

FILE1 -ef FILE2: FILE1FILE2是否指向同一个设 备上的相同inode file1是不是file2硬链接

FILE1 -nt FILE2: FILE1是否新于FILE2mtime

FILE1 -ot FILE2: FILE1是否旧于FILE

另外,Shell还提供了与( -a )、或( -o )、非( ! )三个逻辑操作符用于将测试条件连接起来,其优先级为:"!"最高,"-a"次之,"-o"最低。

例如:

cd /bin
if
[ -e ./notFile -o -e ./bash ]
then
echo '
有一个文件存在!'
else
echo '
两个文件都不存在'
fi

输出结果:

有一个文件存在!

逻辑运算

如果true 1,false 0

与: 1 1 = 1 : 1 1 = 1

1 0 = 0 1 0 = 1

0 1 = 0 0 1 = 1

0 0 = 0 0 0 = 0

短路运算

非:!

! 1 = 0 ! 0 = 1

短路与

第一个为0,结果必定为0

第一个为1,第二个必须要参与运算

短路或

第一个为1,结果必定为1 第一个为0,第二个必须要参与运算

条件性的执行操作符

&& 代表条件性的AND THEN

|| 代表条件性的OR ELSE

Bash的组合测试条件

第一种方式: COMMAND1 && COMMAND2 并且

COMMAND1 || COMMAND2 或者

! COMMAND

如:[ -r FILE ] && [ -w FILE ]

第二种方式: EXPRESSION1 -a EXPRESSION2 并且

EXPRESSION1 -o EXPRESSION2 或者

! EXPRESSION 必须使用测试命令进

EXPRESSION1 -o EXPRESSION2 = COMMAND1 || COMMAND2

EXPRESSION1 -a EXPRESSION2 = COMMAND1 && COMMAND2

[ -r file -a -w file ] 等同于 [ -r FILE ] && [ -w FILE ]

! EXPRESSION

EXPRESSION is false

[ ! EXPRESSION1 -a EXPRESSION2] = -not expression1 -o -not expression2

[ ! EXPRESSION1 -o EXPRESSION2] = -not expression1 -a -not expression2

EXPRESSION1 -a EXPRESSION2

both EXPRESSION1 and EXPRESSION2 are true

EXPRESSION1 -o EXPRESSION2

either EXPRESSION1 or EXPRESSION2 is true

示例:

[root@centos7 ~]#num=60

[root@centos7 ~]#[ $num -gt 30 -a $num -lt 100 ] && echo "right"||echo "error"

right

等同于

[root@centos6 ~]#[ $num -gt 30 ] && [ $num -lt 100 ] && echo "right" ||echo "error"

right

cmd1 &&cmd2 ||cmd3

Cmd1 为假 cmd2 不执行 执行cmd3

cmd1为真 cmd2 执行 不执行cmd3

[root@centos7 ~]#id wang; id wang &> /dev/null && echo "id wang exist" || useradd wang

#!/bin/bash

name=wang; id $name &> /dev/null && { echo "$name exist";exit 100; } ||(useradd wang;echo bing|passwd --stdin $name; )

判断num是不是整数

[root@centos7 ~]#expr 0 + $num && echo "$num is number" || echo "$num is not number" 只能判断非0整数

[root@centos7 ~]#expr 0 + $num && echo "$num is number" || echo "$num is not number"

[root@centos7 ~]#[[ $num =~ ^-?[0-9]+$ ]] && echo "$num is number"|| echo "$num is not number"

使用read命令来接受输入参数变量

v 使用read来把输入值分配给一个或多个shell变量

-p 指定要显示的提示

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

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

-d ‘字符’ 输入结束符

-t N TIMEOUTN

read 从标准输入中读取值,给每个单词分配一个变量 所有剩余单词都被分配给最后一个变量 read -p Enter a filename: FILE

#!/bin/bash

read -s -p "please input your passwd: " pass

echo -e "nyour passwd is $pass"

多个变量

防止扩展 v

反斜线()会使随后的字符按原意解释

$ echo Your cost: $5.00

Your cost: $5.00 v

加引号来防止扩展

? 单引号(’)防止所有扩展

? 双引号(”)也防止所有扩展,但是以下情况例外:

? $(美元符号) 变量扩展

?(反引号) 命令替换

? (反斜线) 禁止单个字符扩展

? !(叹号) 历史命令替换

bash的配置文件 用户登录自动生成bash终端

全局配置:

/etc/profile

/etc/profile.d/*.sh

/etc/bashrc v

个人配置:

~/.bash_profile

~/.bashrc

shell登录两种方式

v 交互式登录:

(1)直接通过终端输入账号密码登录 (2)使用“su - UserName 切换的用户

执行顺序:/etc/profile --> /etc/profile.d/*.sh --> ~/.bash_profile --> ~/.bashrc --> /etc/bashrc v 调用

# .bashrc

# User specific aliases and functions

PS1="[e[31m][u@h W]$[e[0m]"

alias rm='rm -i'

alias cp='cp -i'

alias mv='mv -i' #别名定义

# Source global definitions

if [ -f /etc/bashrc ]; then

. /etc/bashrc

fi

~

~

~ .bashrc ——>/etc/bashrc

~

~

非交互式登录: (1)su UserName (2)图形界面下打开的终端 (3)执行脚本 (4)任何其它的bash实例

执行顺序: ~/.bashrc --> /etc/bashrc --> /etc/profile.d/*.sh

按功能划分,存在两类: profile类和bashrc

vprofile类:为交互式登录的shell提供配置

全局:/etc/profile,/etc/profile.d/*.sh

个人:~/.bash_profile

功用: (1) 用于定义环境变量 (2) 运行命令或脚本

bashrc类:为非交互式和交互式登录的shell提供配置

全局:/etc/bashrc

个人:~/.bashrc

功用: (1) 定义命令别名和函数 (2) 定义本地变量

编辑配置文件生效

修改profilebashrc文件后需生效

两种方法: 1重新启动shell进程 2 . source : . ~/.bashrc

Bash 退出任务

v 保存在~/.bash_logout文件中(用户)

v 在退出登录shell时运行

v 用于 ? 创建自动备份 ? 清除临时文件


v1、让所有用户的PATH环境变量的值多出一个路径,例如: /usr/local/apache/bin

v2、用户root登录时,将命令指示符变成红色,并自动启用如 下别名:rm=rm i cdnet=cd /etc/sysconfig/network-scripts/ editnet=vim /etc/sysconfig/network-scripts/ifcfg-eth0 editnet=vim /etc/sysconfig/network-scripts/ifcfgeno16777736 ifcfg-ens33 (如果系统是CentOS7)

vim .bashrc配置文件中定义

v3、任意用户登录系统时,显示红色字体的警示提醒信息 Hi,dangerous!”

v4、编写生成脚本基本格式的脚本,包括作者,联系方式,版 本,时间,描述等

[root@zab ~]# vim scipt.sh

#!/bin/bash

cat>$1<<eof

#!/bin/bash

######################

#auther:71

#creat-time:`date +%F`

#filename:`basename $1`

######################

Eof

chmod +x $1

vim + $1

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读