码迷,mamicode.com
首页 > 系统相关 > 详细

shell编程基础

时间:2017-11-26 21:59:22      阅读:224      评论:0      收藏:0      [点我收藏+]

标签:shell

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, by reference, 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

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

 

~                                                                                                         

~                                                                                                                           

 退出状态

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

 ?代表成功,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

 


shell编程基础

标签:shell

原文地址:http://blog.51cto.com/13157015/2044463

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!