回顾:权限、bash


权限和用户:Linux


进程:属主、属组


文件:属主、属组、其它


r、w、x


chmod:

OCTAL-MODE

u,g,o,a = 

u,g,o,a +/-


bash特性:

快捷操作、补全


ELF:可执行文件格式,二进制文件

#!/bin/bash


程序=指令+数据

变量:

弱类型语言:

1、不强制区分变量的类型,无论存储何种数据,均以字符格式进行;

2、无须事先声明;用到时,直接使用,直接赋值;


bash: 动态编程语言,是弱类型语言;


bash的特性之九:bash中的变量

变量的类型:

本地变量:只对当前shell进程有效,对其子shell以及其它shell都无效,是在内存中的,进程结束则变量over!!!!!!!!

定义变量: [set]Var_Name="Value"

引用变量: ${Var_Name}

撤销变量: unset Var_Name


(不带任何参数的set指令能显示当前进程的所有变量,不仅仅是本地变量,还有下面几种变量)


局部变量:仅对局部代码生效

local Var_Name="Value"

环境变量:对当shell进程及其子shell有效;

export Var_Name="Value"   进对当前进程用户有效,如关闭则无效,重启启动则使用预先配置好的了。

Var_Name="Value"

export Var_Name

导出

位置变量:

$1, ..., $n

./first.sh 2 8   脚本传入参数

特殊变量:

$0: 脚本名称自身

$?: 上一条命令的执行状态;  ?为状态返回值

状态用数字来表示:0-255;

0: 成功

1-255: 失败    1 2 127 255是系统预留的

[root@zhenzhen ~]# ll -d /etc

drwxr-xr-x. 61 root root 4096 Oct  8 11:50 /etc

[root@zhenzhen ~]# echo $?

0

[root@zhenzhen ~]# lll /etc

   -bash: lll: command not found

[root@zhenzhen ~]# echo $?

127

执行完指令后,可以用echo $?去查看

$$

$!

$#

$*



变量的命名要求:

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

不能以数字开头;

不能使用程序中的关键字;

见名知义;totalWeight 



例:新建十个用户:mageduuser1-mageeduuser10

# useradd mageeduuser1




练习:

完成以下任务:

  (1)新建系统组mysql;新建系统用户mysql,要求其没有家目录且shell为/sbin/nologin;


  (2)新建GID为600的组magedu;新建用户gentoo,要求其家目录为/users/gentoo,密码同用户名;



  (3)新建用户centos,其家目录为/users/centos,密码同用户名;



  (4)新建用户www,其家目录为/users/www;删除www用户,但保留其家目录;


  (5)用户gentoo和centos均以magedu为其附加组;

         


完成以下任务:

(1) 切换至centos用户,定义本地变量FirstVar,其值为“test variable”;

# su - centos

# FirstVar="test variable"


(2) 另启一个终端,使用gentoo用户查看FirstVar变量的值;如果没有值,为什么?


(3) 声明一个变量CurTime,其值为当前系统时间;

# curTime=`date +%T`


(4) 使用echo命令显示“The current time is:”,is后跟上CurTime变量的值;

# echo "The current time is: $curTime."


(5) 回至centos用户的终端:复制/etc/pam.d目录至/tmp目录中,并重命名为test;

# cp -r /etc/pam.d /tmp/test


(6) 声明变量fileName,其值为刚才复制的目录/tmp/test;

# fileName="/tmp/test"


(7) 修改变量fileName所表示的目录及其内部所有文件的其它用户均没有任何访问权限;

# chmod -R o= $fileName


(8) centos用户是否可以修改变量fileName所表示的目录的属主和属组?如果能,将其改为gentoo用户和gentoo组;如果不能,则使用root用户修改;




set指令 查看当前shell用户所有的变量,包括本地变量,环境变量等


环境变量:用来bash的工作特性,也就是说明当前shell进程的工作特性,如进程完了则变量释放,用于保存当前会话的属性信息;


显示所有环境变量:export, env, printenv

定义:export Var_Name="Value"

PATH, PS1

[root@zhenzhen ~]# export PATH=$PATH:/root/sbin  在PATH变量中添加新的路径


这些变量都是对当前进程的变量,进程销毁的变量释放,进程刚建立时,通过读取配置文件设定基本变量



bash的配置文件:持久保存用户配置,分为两类:

profile类:为交互式登录的用户提供配置

/etc/profile:全局,对所有用户都生效

/etc/profile.d/*.sh:全局,对所有用户都生效

这个目录下文件的作用是将配置文件合理安排用的,例如需要加入java的bin,可以在目录下建文件java.sh即可

~/.bash_profile:个人配置,仅对当前用户有效


功能:

设定环境变量

运行命令或脚本


bashrc类:非交互工登录用户提供配置

/etc/bashrc: 全局

~/.bashrc: 个人配置

系统启动时都会读取一次

功用:

设定本地变量

定义命令别名



登录类型:

交互式登录:

直接通过终端输入用户信息登录系统;

su - UserName或su -l UserName;


非交互式登录:

su UserName

图形界面的终端

执行脚本(执行之前会先通过配置文件设置解释环境,再使用解释器)


新增配置的生效方式:

通知shell重读配置文件的命令:

source (.这个点是简写格式)

. FILE

重新登录(推荐使用)


!!!!!!!!!!!!重要!!!!!!!!!!!!!!!!!!!!!1

系统读取配置文件信息的次序:

交互式登录用户:

/etc/profile --> /etc/profile.d/*.sh --> ~/.bash_profile --> ~/.bashrc --> /etc/bashrc


非交互式登录用户:

~/.bashrc --> /etc/bashrc --> /etc/profile.d/*.sh



?思考:

Java, JVM, /usr/java/latest/bin


echo指令+$ 是找出当前shell进程中的变量信息



bash脚本:面向过程的编程中

顺序执行:默认法则,逐条执行各语句

选择执行:分支,条件判断,符合条件的分支予以执行;

循环执行:将同一段代码反复执行有限次,所以,循环必须有退出条件,否则将陷入死循环;


程序代码:语句和表达式组成


控制语句:


bash循环控制语句:

for

while

until


for循环:

for var_Name in 列表; do

语句1

语句2

...

done


for userName in gentoo mandriva debian; do

useradd $userName

done


语法错误检测:

# bash -n 脚本文件

bash -n autoFile     此时不用改autoFile的执行权限,因为bash就是执行


写一个脚本:添加10个用户,user101-user110


列表的生成方法:

生成数字序列:{start..end}、seq [start] [step] end


#!/bin/bash


for userName in `seq 101 110`; do

 useradd user$userName

 echo "Add user$userName successfully."

done


$符号:

不同的地方$符号的定义不同,在bash里这个符号一般表示普通用户的命令提示符(可更改),在bash脚本里。$开头表示变量

有时在shell命令行里输入编程语言,有$(seq 1 10),还表示命令提示

普通在命令行中$表示当前进程变量


练习:写一个脚本,用file命令显示/var/log目录下每个文件的内容类型;

提示:列表生成的方法为/var/log/*


#!/bin/bash

#

dirName=/var/log

for fileName in $dirName/*; do

file $fileName

done 


bash -n /path/to/script



循环:退出条件, 元素列表遍历结束


for varName in LIST

do

statement1

...

done



练习:写一个脚本,

1、创建/tmp/scripttest目录,用变量保存目录名;

2、在目录里创建测试文件tfile1-tfile20;

3、创建用户testuser1和testuser2; 

4、将tfile1-tfile10的属主和属组改为testuser1;

5、将tfile11-tfile20的属主和属组改为testuser2;


自己写的

[zhenzhen@zhenzhen ~]$ vi shell1.sh 

#!/bin/bash


dirMy=/tmp/scripttest

mkdir $dirMy

for fileNumber in `seq 1 20`;do

 touch ${dirMy}/tfile${fileNumber}

done


useradd testuser1

useradd testuser2


for fileNumber in `seq 1 10`;do

 chown testuser1:testuser1 ${dirMy}/tfile${fileNumber}

done


for fileNumber in `seq 11 20`;do

 chown testuser2:testuser2 ${dirMy}/tfile${fileNumber}

done


参考文件

#!/bin/bash

dirName=/tmp/scripttest


mkdir $dirName

for fileNo in {1..20}; do

touch $dirName/tfile$fileNo

echo "Create $dirName/tfile$fileNo finished"

done 


useradd testuser1

useradd testuser2


for fileNo in {1..10}; do

chown testuser1:testuser1 $dirName/tfile$fileNo

done


for fileNo in {11..20}; do

chown testuser2:testuser2 $dirName/tfile$fileNo

done



#!/bin/bash

dirName=/tmp/scripttest


useradd testuser1

useradd testuser2


mkdir $dirName

for fileNo in {1..10};do

touch $dirName/tfile$fileNo

chown testuser1:testuser1 $dirName/tfile$fileNo

done




文本处理类的命令:wc, word count

wc [option] [file]...

-l: 统计行数

-c: 统计字节数

-w;统计单词数


tr: 转换字符或删除字符,需要使用管道,一个命令的输出通过管道作为另一个命令的输入

tr '集合1' '集合2'

tr -d '字符集合'

[root@zhenzhen ~]# echo "hello world" | tr 'abcdefg' 'ABCDEFG'

hEllo worlD

[root@zhenzhen ~]# echo "hello world" | tr -d 'ABCDEFG'

hello world

[root@zhenzhen ~]# echo "hello world" | tr -d 'abcdefg'

hllo worl

这里使用到了管道作为tr的输入,就是符号 |


[root@zhenzhen ~]# cat /etc/issue | tr 'a-z' 'A-Z'

CENTOS RELEASE 6.5 (FINAL)

KERNEL \R ON AN \M


cut: 也是通过管道送入

This is a test line.

-d字符:指定分隔符

-f#: 指定要显示字段

单个数字:一个字段

逗号分隔的多个数字:指定多个离散字段

-:连续字段,如3-5;每个数字代表一个字段


也可以直接处理文本,这里不会改变文本,只是执行显示

[root@zhenzhen ~]# cut -d: -f1,7 /etc/passwd

root:/bin/bash

bin:/sbin/nologin

daemon:/sbin/nologin

adm:/sbin/nologin


sort: 按字符进行比较,后面跟文件,对文件内容进行排序,默认是ASC码,也可使用管道

sort [option] file...

-f: 忽略字符大小写;

-n: 比较数值大小;

-t: 指定分隔符

-k: 指定分隔后进行比较字段

-u: 重复的行,只显示一次;


[root@zhenzhen ~]# sort -n -t: -k3 /etc/passwd

root:x:0:0:root:/root:/bin/bash

bin:x:1:1:bin:/bin:/sbin/nologin

daemon:x:2:2:daemon:/sbin:/sbin/nologin

adm:x:3:4:adm:/var/adm:/sbin/nologin


uniq: 移除重复的行

-c:显示每行重复的次数,不连续的重复行不认为是重复的

-d:仅显示重复过的行

-u: 仅显示不曾重复的行

[root@zhenzhen ~]# sort testFile | uniq -c

     1 101

     1 12

     2 14

     1 1wsa

     1 aq

     2 ax

     1 sas


练习:

1、统计/bin、/usr/bin、/sbin和/usr/sbin等各目录中的文件个数;

# ls /bin | wc -l

2、显示当前系统上所有用户的shell,要求,每种shell只显示一次;

# cut -d: -f7 /etc/passwd | sort -u

3、取出/etc/passwd文件的第7行;

# head -7 /etc/passwd | tail -1

4、显示第3题中取出的第7行的用户名;

# head -7 /etc/passwd | tail -1 | cut -d: -f1


# head -7 /etc/passwd | tail -1 | cut -d: -f1 | tr 'a-z' 'A-Z'

5、统计/etc目录下以P或p开头的文件个数;

# ls -d /etc/[Pp]* | wc -l






练习:写一个脚本,用for循环实现

显示/etc/init.d/functions、/etc/rc.d/rc.sysinit和/etc/fstab各有多少行;


#!/bin/bash

for fileName in /etc/init.d/functions /etc/rc.d/rc.sysinit /etc/fstab; do

wc -l $fileName

done


#!/bin/bash

for fileName in /etc/init.d/functions /etc/rc.d/rc.sysinit /etc/fstab; do

lineCount=`wc -l $fileName | cut -d' ' -f1`

echo "$fileName: $lineCount lines."

done


#!/bin/bash

for fileName in /etc/init.d/functions /etc/rc.d/rc.sysinit /etc/fstab; do

echo "$fileName: `wc -l $fileName | cut -d' ' -f1` lines."

done


练习:写一个脚本

将上一题中三个文件的复制到/tmp目录中;

用for循环实现,分别将每个文件的最近一次的修改时间改为2011年9月15号13点27分;

#!/bin/bash

for fileName in /etc/init.d/functions /etc/rc.d/rc.sysinit /etc/fstab; do

cp $fileName /tmp

baseName=`basename $fileName`

touch -m -t 201109151327 /tmp/$baseName

done



练习:写一个脚本

显示/etc/passwd中第3、7和11个用户的用户名和ID号;

#!/bin/bash

#

for lineNo in 3 7 11; do

userInfo=`head -n $lineNo /etc/passwd | tail -1 | cut -d: -f1,3`

echo -e "User: `echo $userInfo | cut -d: -f1`\nUid: `echo $userInfo |cut -d: -f2`"

done



for:通过使用一个变量去遍历给定列表中的每个元素,在每次变量赋值时执行一次循环体,直至赋值完成所有元素退出循环;

总结:生成列表的方式

1、直接给出列表;

2、使用文件名通配的机制生成列表  例如 /etc/p*

3、可以使用{}或seq命令生成数字序列  1, $lineCount   `seq 1 $lineCount`  {1..$lineCount}

4、使用命令生成