天天看点

Day01 Shell脚本编程一、shell环境及特性二、Shell脚本设计三、写脚本四、变量五、单引号&双引号&反引号

解释器:负责向内核翻译及传达用户/程序指令

解释器 车

shell 汽车

bash 宝马、奔驰、法拉利

文件里面的内容就是系统已安装的解释器

修改老用户的默认解释器

创建新用户时指定默认解释器

ctrl+l清屏

ctrl+c终止当前运行的程序

ctrl+a移动光标到行首

ctrl+e移动光标到行尾

ctrl+w删除当前光标前面的一个单词

esc+d删除当前光标后面的一个单词

ctrl+u删除当前光标到行首的所有内容

ctrl+k删除当前光标到行尾的所有内容

ctrl+f向前移动一个字符

ctrl+b向后移动一个字符

alt+b 向前移动一个单词

alt+f 向后移动一个单词

RHEL7.2才支持补齐选项,老版本可通过bash-completion包提供选项补齐的功能

grep HISTSIZE /etc/profile#查看历史命令默认保存条数

history | wc -l#查看当前使用了多少条命令

!100#执行第100条命令

!cat#从后到前,查找最近执行的cat命令

history -c#清除历史命令

~/.bash_history

alias

unalias

/etc/bashrc

~/.bashrc

标准输出&1

错误输出&2

标准输入&0

对脚本来说,重定向非常重要,相当于给执行脚本做了个日志记录

1>正确输出 1>>正确追加输出

2>错误输出 2>>错误追加输出

&>将正常输出、错误输出重定向同一个文件

/dev/null 2>&1 相当于1>/dev/null 2>/dev/null。是将标准出错重定向到标准输出,最后一个&表示取标准设备。 echo 'error' >&2 把echo出来的结果 重定向到 错误输出. <重定向输入 在linux里面管道非常重要!!! 把前一个命令的输出作为给后面的命令的输入 因为linux命令设计的原则是3S(simple、small、speed),软件越大启动越慢、漏洞越多。管道具体使用上就是用来组合多个命令,来实现复杂的功能 yum list|grep abc|wc -l echo "content" | mail -s "title" receipt 缺点是邮件内容不能写太多,优点是不用另外创建文件 mail -s "title" receipt < mail.txt 缺点是需要先创建文件,优点是可以写很多内容 扩展名是.sh 顶格第一行必须是#!/bin/bash,表示该脚本指定由bash作为脚本解释器 #为注释符,注释可以写时间、版本、功能、联系人 chmod +x 脚本名 ./脚本名#相对路径 /root/脚本名#绝对路径 bash 脚本名#指定解释器,即使脚本没有执行权限,也同样能执行脚本 上面的执行方式都会开启子进程 但是注意!source 脚本名是不会开启子进程的。 在特例中,比如脚本中只有一行exit,执行脚本后会退出当前bash

$PATH 命令搜索路径

#!/bin/bash

echo "hello the word"

if [ -d /etc/yum.repos.d ];then

rm -fr /etc/yum.repos.d/*

echo '[dvd]

name=rhel

gpgcheck=0' >/etc/yum.repos.d/dvd.repo

else

mkdir -p /etc/yum.repos.d/

fi

yum clean all >/dev/null

yum -y install vsftpd 2>/var/log/ins_vsftpd_err.log >/dev/null

systemctl restart vsftpd && systemctl enable vsftpd >/dev/null

read -p "请输入用户名:" name

#关闭回显

stty -echo

read -p "请输入密码:" pass

#打开回显

stty echo

useradd $name

echo $pass | passwd --stdin $name

echo '03 03 5 tar -czf /root/log-$(date+%F).tar.gz /var/log' >>/var/spool/cron/root

思路:如何检测登录用户数量?如何判断大于2?如何发邮件?

#判断本机登录的用户数是否大于2,如果大于2,则发邮件给root

num=<code>who|wc -l</code>

[ $num -gt 2 ] &amp;&amp; mail -s Error root &lt;/root/mail.txt

#mail.txt是要发的邮件内容

[ -d /root/cd ] &amp;&amp; mount /ISO/rhel7.iso /cd || mkdir /cd;mount /ISO/rhel7.iso /cd

[ -d /root/cd ] || mkdir /cd &amp;&amp; mount /ISO/rhel7.iso /cd

[ ! -d /root/cd ] &amp;&amp; mkdir /cd;mount /ISO/rhel7.iso /cd

思路:只关心最后得出的和。如何输出1..100?输出的值存入另一个变量?另一个变量存储最后得出的和

j=0

for i in {1..100}

do

let j+=i

done

echo $j

思路:如何显示每个文件?如何打包并保存?

for n in <code>ls /var/log</code>

tar -zcf /tmp/$n.tar.gz /var/log/$n &amp;&gt;/dev/null

思路:读取键盘输入?求和并存在另一个变量内?如果输入0则结束循环并输出和

RESULT=0

while :

read -p "请输入一个数[0结束]:" NUM

[ $NUM -eq 0 ] &amp;&amp; break

let RESULT+=$NUM

echo $RESULT

实际屏幕输出:

11=1

21=2 22=4

31=3 32=6 33=9

......

91=9 92=18 93=27 94=36 95=45 96=54 97=63 98=72 9*9=81 

思路:i={1..9} j={?} 要打出三角形,核心是i&lt;=j

脚本:

for j in {1..9}

for i in {1..9}

echo -en "$i$j=$[ij]\t"

[ $i -eq $j ] &amp;&amp; break

echo

for i in <code>seq $j</code>

思路:棋盘的格式是黑白相间

for n in {1..4}

for i in {1..4}

echo -en "\033[44m \033[0m"

echo -en "\033[45m \033[0m"

for j in {1..4}

更优秀的代码:

color(){

echo -en "\033[4$1m \033[0m"

echo -en "\033[4$2m \033[0m"

}

for i in {1..8}

y=$[i%2]

[ $y -eq 1 ] &amp;&amp; color 7 0 || color 0 7

思路:前一天的数量y等于今天的数量(x+1)2

x=1

x=$[(x+1)2]

思路:如何计算1+...x的和?不输入值该如何处理?

sum=0

read -p "请输入一个数:" num

num=${num:-100}

for i in <code>seq $num</code>

do 

let sum+=i 

done 

echo "从1到${num}的求和值为:$sum"

exit

思路:num1存最小值,num2存中间,num3存最大值,tmp作为中间变量。有多少种可能呢?

num1&gt;num2&gt;num3

num1&lt; num2&lt; num3

num2 &lt; num3

num2

首先if判断num1和num2比大小。如果num1大,则把num1和num2交换,保证num1存放的是小值;如果num2大,则不做操作,结束这个判断

然后再来个if判断num1和num3比大小。如果num1大,则把num1和num3交换,保证num1存放的是最小值;如果num3大,则不做操作,结束这个判断

最后的if判断num2和num3比大小。如果num2大,则把num2和num3交换,保证num3存放的是最大值;如果num3大,则不做操作,结束这个判断。

从小到大输出$num1 $num2 $num3

#num1存最小值,num2存中间,num3存最大值

num1=$RANDOM

num2=$RANDOM

num3=$RANDOM

tmp=0

if [ $num1 -gt $num2 ];then

tmp=$num2;num2=$num1;num1=$tmp

if [ $num1 -gt $num3 ];then

tmp=$num1;num1=$num3;num3=$tmp

if [ $num2 -gt $num3 ];then

tmp=$num3;num3=$num2;num2=$tmp

echo $num1 $num2 $num3

以固定名称来存放可能会变化的值

若指定的变量名存在,则相当于给变量赋值

等号两边不能有空格

只能用数字、字母和下划线组成

不能以数字开头

变量名=变量值

FROM=/etc/

read -p "提示" 变量名#只定义变量名,不赋值。由使用该命令的人来赋值

使用位置变量$1、$2等

通过管道|把前面命令的输出作为现在命令的输入

$FROM

echo $FROM

echo ${FROM}

配置文件:/etc/profile、~/.bashrc

PATH

HOME

USER

UID

HOSTNAME

PS1 一级提示符

PS2 二级提示符

$0:脚本自身的名字

$1:位置变量1

$2:位置变量2

$:所有变量

$ @ :所有变量。

$和$@都表示传递给函数或脚本的所有参数,不被双引号(" ")包含时,都以"$1" "$2" … "$n" 的形式输出所有参数。 

但是当它们被双引号(" ")包含时,"$*" 会将所有的参数作为一个整体,以"$1 $2 … $n"的形式输出所有参数;"$@" 会将各个参数分开,以"$1" "$2" … "$n" 的形式输出所有参数。

$#:所有变量的数量

$$:脚本运行后的PID

$!:显示最后一个被放到后台的进程PID

$?:上一条命令执行状态,值等于0为正确,值非0就是错误

自定义变量默认就是局部变量

存在于脚本函数(function)中的变量也是局部变量。

要以 local 变量名方式进行声明,使之只在本函数作用域内有效,防止变量在函数中的命名与变量外部程序中变量重名造成程序异常。

局部变量默认只在当前shell环境中有效,无法在子shell环境中使用

可以通过export命令将局部变量声明为全局变量

系统变量默认就是全局变量

全局变量在当前shell环境及子、孙等shell环境中有效

/etc/profile

export 变量名#将局部变量声明为全局变量

export -n 变量名#取消声明

双引号可以界定一个完整的字符串

echo a b

echo "a b"

单引号可以界定一个完整的字符串,而且可以屏蔽特殊符号($\ ),原封不动输出。

<code>命令</code> 仅可以放命令,提取的是命令的结果

$(命令) 仅可以放命令,提取的是命令的结果

本文转自 goldwinner 51CTO博客,原文链接:http://blog.51cto.com/355665/2068827,如需转载请自行联系原作者