0x01 What’s Shell
Shell 是一个应用程序,它连接了用户和 Linux 内核,让用户能够更加高效、安全、低成本地使用 Linux 内核,这就是 Shell 的本质。
Shell 本身并不是内核的一部分,它只是站在内核的基础上编写的一个应用程序,它和 QQ、迅雷、Firefox 等其它软件没有什么区别。然而 Shell 也有着它的特殊性,就是开机立马启动,并呈现在用户面前;用户通过 Shell 来使用 Linux,不启动 Shell 的话,用户就没办法使用 Linux。
Shell 有哪些系统中:
#vi /etc/shells #shells里写了可以用的shell
默认是bash
0x02 Shell 脚本的执行方式
0x021 echo命令
#echo [选项] [输出内容]
选项:
-e : 支持反斜线控制的字符转换(具体参见下表)
-n : 取消输出后末行换行符(就是内容输出后不换行)
默认情况下,echo 不会解析以反斜杠\
开头的转义字符。比如,\n
表示换行,echo 默认会将它作为普通字符对待。
转义字符 | 功能 |
---|---|
\a | 发出警告声; |
\b | 删除前一个字符; |
\c | 最后不加上换行符号; |
\f | 换行但光标仍旧停留在原来的位置; |
\n | 换行且光标移至行首; |
\r | 光标移至行首,但不换行; |
\t | 插入tab; |
\v | 与\f相同; |
\ | 插入\字符; |
\nnn | 插入nnn(八进制)所代表的ASCII字符; |
0x022 history
历史命令,他其实是查看了~/.bash_history文件
#history [选项]
选项:
-w : 强制把当前的历史写入到配置文件里,如果没有手工指点,则放进默认的~/.bash_history里
-e : 清空历史命令。当前和配置文件里面都会清楚掉。
0x03 Bash常用快捷键
快捷键 | 快捷键说明 |
---|---|
CTRL-A | 将光标移到行首(在命令行下) |
CTRL-C | 中断,终结一个前台作业。 |
CTRL-E | 将光标移动到行尾(在命令行下) |
CTRL-K | CTRL-K会删除从光标所在处到行尾的所有字符。 |
CTRL-L | 跳纸,换页(Formfeed),清屏。 清空终端屏幕。在终端上,这个命令的作用和clear命令一样。但当这个命令发送到打印机时,Ctrl-L会直接跳到纸张(Paper sheet)的末尾。 |
CTRL-R | 回溯搜索(Backwards search)history缓冲区内的文本(在命令行下)。注意:按下之后,提示符会变成(reverse-i-search)”:输入的搜索内容出现在单引号内,同时冒号后面出现最近最匹配的历史命令。 |
CTRL-Y | 将之前已经清除的文本粘贴回来(主要针对CTRL-U或CTRL-K)。 |
CTRL-U | 擦除从光标位置开始到行首的所有字符内容。在某些设置下,CTRL-U会不以光标位置为参考而删除整行的输入。 |
0x04 输入输出重定向
0x041 输出重定向
文件描述符 | 文件名 | 类型 | 硬件 |
---|---|---|---|
0 | stdin | 标准输入文件 | 键盘 |
1 | stdout | 标准输出文件 | 显示器 |
2 | stderr | 标准错误输出文件 | 显示器 |
Linux 程序在执行任何形式的 I/O 操作时,都是在读取或者写入一个文件描述符。一个文件描述符只是一个和打开的文件相关联的整数,它的背后可能是一个硬盘上的普通文件、FIFO、管道、终端、键盘、显示器,甚至是一个网络连接。
stdin、stdout、stderr 默认都是打开的,在重定向的过程中,0、1、2 这三个文件描述符可以直接使用。
在输出重定向中,>
代表的是覆盖,>>
代表的是追加。
注意
输出重定向的完整写法其实是fd>file
或者fd>>file
,其中 fd 表示文件描述符,如果不写,默认为 1,也就是标准输出文件。
当文件描述符为 1 时,一般都省略不写,如上表所示;当然,如果你愿意,也可以将command >file
写作command 1>file
,但这样做是多此一举。
当文件描述符为大于 1 的值时,比如 2,就必须写上。
需要重点说明的是,fd
和>
之间不能有空格,否则 Shell 会解析失败;>
和file
之间的空格可有可无。为了保持一致,我习惯在>
两边都不加空格。
0x042 输入重定向
符号 | 说明 |
---|---|
command <file | 将 file 文件中的内容作为 command 的输入。 |
command <<END | 从标准输入(键盘)中读取数据,直到遇见分界符 END 才停止(分界符可以是任意的字符串,用户自己定义)。 |
command <file1 >file2 | 将 file1 作为 command 的输入,并将 command 的处理结果输出到 file2。 |
和输出重定向类似,输入重定向的完整写法是`fd,其中 fd 表示文件描述符,如果不写,默认为 0,也就是标准输入文件。
0x05 多命令顺序执行
多命令执行符 | 格式 | 作用 |
---|---|---|
; | 命令1;命令2 | 多命令顺序执行,命令之间没有任何逻辑联系 |
&& | 命令1&&命令2 | 当命令1正确执行($?=0),则命令2才会执行。当命令1执行不正确($?≠0),则命令2不执行 |
|| | 命令1||命令2 | 当命令1正确($?≠0),则命令2才会执行。当命令1正确命令2不执行 |
0x06 bash中其他的符号
符号 | 作用 |
---|---|
‘’ | 单引号。在单引号中所哟普的特殊符号都没有含义 |
“” | 双引号。在双引号中他也输符号都没有特殊含义,但是”$”,”\“,“^”是例外,拥有”调用变量“,”转义“,”引用命令“的特殊含义 |
`` | 反引号。反引号括起来的内容是系统命令,在Bash中会先执行它。和$()作用一样,不过推荐$因为反引号很容易看错。 |
$() | 和反引号作用一样,用来引用系统命令 |
() | 用于一串命令执行时,()中的命令会在子shell中执行。 |
{} | 用于一串命令执行时,{}中的命令会在当前Shell中执行。也可以用于变量变形与替换。少用 |
[] | 用于变量的测试 |
# | 在Shell脚本中。#开头的行代表注释。 |
$ | 用德语调用变量的值,如果需要调用变量name就用$name方式。 |
\ | 转义符。 |
$(()) | 双小括号表示运算 |
- ()执行一串命令时,需要重新开一个子shell进行执行
- {}执行一串命令时,是在当前shell执行
- ()和{}都是把一串的命令放在括号里面执行,并且命令之间用;号隔开。
- ()最后一个命令可以不用分号
- {}最后一个命令要用分号。
- {}的第一个命令和左括号之间必须要有一个空格。
- ()里的各种命令不必和括号有空格
- ()和{}里面的某个命令的重定向只影响该命令,但括号外的重定向影响到括号里面。
0x07 Bash的变量和运算符
什么是变量
变量名由子母炮,数字,和下划线组成,但是不能以数字开头
在Bash中,变量的默认类型都是字符串类型,如果要进行数值运算,则必修指定变量类型为数值型。
变量用等号赋值
变量的值如果由空格,需要使用单引号或双引号包括。如
test="hello world!"
,其中双引号括起来的内容,”$”,”\“和反引号都有特殊含义,而单引号括起来的内容都是普通字符。在变量的值中,可以使用”\“转义
如果需要增加变量的值,那么可以进行变量值的叠加。不过变量需要用双引号包含”$变量名”或用${变量名}包含变量名。如下
#test=123 #tset="$test"456 #echo $test 123456
如果是把命令的结果作为变量的值赋予变量,则需要反引号或者$()包含命令。例如
#test=$(date) #echo $test
0x08 变量分类
- 用户定义变量:这种变量是最常见的变量,由用户定义变量名和变量值
- 环境变量:这种变量主要保存的是系统操作环境相关的数据。
- 位置参数变量:这种变量主要是用来向脚本当中传递参数或数据的,变量名不能定义,变量作用是固定的。
- 预定义变量:是Bash中已经定义好的变量,变量名不能自定义,变量也起固定的作用。
名称 | 作用 | 内容 | |
---|---|---|---|
用户自定义变量 | 自定义 | 自定义 | 自定义 |
用户自定义环境变量 | 自定义 | 自定义 | 自定义 |
系统自定环境变量 | 确定 | 确定 | 自定义 |
位置参数变量 | 确定 | 确定 | 自定义 |
预定义变量 | 确定 | 确定 | 自定义 |
查看变量
#set [选项]
选项:
-u : 如果设定此选项,调用未声明变量时会报错(默人无任何提示)
-x : 如果设定这个选项,在命令执行前,会把命令先输出一次
同样是临时的要写进环境变量。
删除变量
#unset "变量名"
0x081 环境变量
用户环境变量:
环境变量设置
#export age="18" #使用export声明的变量即是环境变量。
环境变量查询和删除
#unset gender #env | grep gender
用户自带的环境变量:
PATH: 系统查找命令的路径
#echo $PATH #查看环境变量 #PATH="PATH":/root/ #添加环境变量
0x82 PS1环境变量
Linux PS1 是修改提示的
\d :代表日期,格式为weekday month date,例如:"Mon Aug 1"
\H :完整的主机名称。例如:我的机器名称为:fc4.linux,则这个名称就是fc4.linux
\h :仅取主机的第一个名字,如上例,则为fc4,.linux则被省略
\t :显示时间为24小时格式,如:HH:MM:SS
\T :显示时间为12小时格式
\A :显示时间为24小时格式:HH:MM
\u :当前用户的账号名称
\v :BASH的版本信息
\w :完整的工作目录名称。家目录会以 ~代替
\W :利用basename取得工作目录名称,所以只会列出最后一个目录
\# :下达的第几个命令
\$ :提示字符,如果是root时,提示符为:# ,普通用户则为:$
—注意$后面有一个空格!如果没有空格的话,将会报错!
修改的时候直接
# PS1='[\u@\h \w]\$ ' #临时生效
# vi /etc/bashrc #永久生效
0x83 语系变量
LANG定义了Linux系统的主语系环境,这个变量的默认值是:
[root@localhost ~]# echo $LANG
en_US.UTF-8
查看已经安装的语系
#locale
LANG=en_US.UTF-8
LC_CTYPE="en_US.UTF-8"
LC_NUMERIC="en_US.UTF-8"
LC_TIME="en_US.UTF-8"
LC_COLLATE="en_US.UTF-8"
LC_MONETARY="en_US.UTF-8"
LC_MESSAGES="en_US.UTF-8"
LC_PAPER="en_US.UTF-8"
LC_NAME="en_US.UTF-8"
LC_ADDRESS="en_US.UTF-8"
LC_TELEPHONE="en_US.UTF-8"
LC_MEASUREMENT="en_US.UTF-8"
LC_IDENTIFICATION="en_US.UTF-8"
LC_ALL=
/etc/sysconfig/il8n
定义系统的默认语系。
0x84 位置参数变量
位置参数变量 | 作 用 |
---|---|
$n | n 为数字,$0 代表命令本身,$1〜$9 代表第 1〜9 个参数,10 以上的参数需要用大括号包含, 如${10} |
$* | 这个变量代表命令行中所有的参数,把所有的参数看成一个整体 |
$@ | 这个变量也代表命令行中所有的参数,不过 $@ 把每个参数区别对待 |
$# | 这个变量代表命令行中所有参数的个数,普通话统计参数的个数 |
在Shell 中$1,2,3,4表示用户输入的第一,二,三,四个参数。0表示命令本身 他是传参的一种,不适合给普通用户使用
$*和$@区别就是,$*吧所有的参数一次性赋值给$*.$@把参数一次一次的赋值给$@.
0x85 预定义变量
预定义变量 | 作 用 |
---|---|
$? | 最后一次执行的命令的返回状态。如果这个变量的值为 0,则证明上一条命令正确执行;如果这 个变量的值为非 0 (具体是哪个数由命令自己来决定),则证明上一条命令执行错误 |
$$ | 当前进程的进程号(PID) |
$! | 后台运行的最后一个进程的进程号(PID) |
$?可以判断命令是否正确执行
0x86 声明变量类型
既然所有变量的默认类型都是字符串型,那么我们只要把特定的变量声明成整数型就可以了。
#declare [+/-][选项] 变量名
选项:
- : 给变量设定类型属性
+ : 取消变量的类型属性
-a : 声明位数组型
-i : 声明位整数型
-r : 声明变量为只读。注意一旦只读,即声明就不能再更改变量的值也不能删除,也没有追加。
-x : 将变量声明为环境变量
-p : 显示指定变量的被声明类型
0x09 接收键盘输入
#read [选项] [变量名]
选项:
-p "提示信息" : 等待read输入时,输出提示信息
-t 秒数 : read命令会一直等待用户输入,使用此选项可以指定等待时间
-n 字符数 : 规定字符数
-s : 隐藏输入数据,适用于机密信息输入
变量名:
变量名可以自定义,如果不指定变量名,会把输入报错入默认变量REPLY
#!/bin/bash
read -t 30 -p "plase input number1" number1
0x10 变量类型
数值型:
declare -i i
数组:
# name[0]="this is shuzu"
# name[1]="shuzu is this"
# echo ${name}
this is shuzu
# echo${name[*]}
this is shuzu shuzu is this
环境变量:
#declare -x test=123 #把test声明为环境变量
#declare +x test=123 #取消test的环境变量
## export 只是declare -x 的简写可以看成 alsas "export"="declare -x"
0x11 shell运算符
数值运算的方法
#!/bin/bash $a=11 $b=22 $d=$(expr $a + $b) 注意+号两端一定要有空格不然就是连接字符。少用 let $e=$a+$b 少用 $f=$$(($a+$b)) 推荐使用
优先级 | 运算符 | 说 明 |
---|---|---|
13 | -,+ | 单目负、单目正 |
12 | !,~ | 逻辑非、按位取反或补码 |
11 | *, /, % | 乘、除、取模 |
10 | +, - | 加、减 |
9 | <<, >> | 按位左移、按位右移 |
8 | <=, >=, <, > | 小于或等于、大于或等于、小于、大于 |
7 | == ,!= | 等于、不等于 |
6 | & | 按位与 |
S | ^ | 按位异或 |
4 | | | 按位或 |
3 | && | 逻辑与 |
2 | II | 逻辑或 |
1 | =,+=,•=,*=,/=,%=,&=, |=, <<=, >>= | 赋值、运算且赋值 |
0x12 变量测试与内容置换
变量置换方式 | 变量y没有设置 | 变量y为空值 | 变量y设置值 |
---|---|---|---|
x=${y-新值} | x= 新值 | x 为空 | x=$y |
x=${y:-新值} | x= 新值 | x= 新值 | x=$y |
x=${y+新值} | x 为空 | x= 新值 | x=新值 |
x=${y:+新值} | x 为空 | x 为空 | x=新值 |
x=${y=新值} | x= 新值;y=新值 | x 为空;y值不变 | x=$y;值不变 |
x=${y:=新值} | x= 新值;y= 新值 | X= 新值;y= 新值 | x=$y;y值不变 |
x=${y?新值} | 新值输出到标准错误输出(屏幕) | x 为空 | x=$y |
x=${y:?新值} | 新值输出到标准错误输出 | 新值输出到标准错误输出 | x=$y |
0x13 环境变量配置文件
0x131 登陆时环境配置文件加载顺序
#cource 配置文件
或
# .配置文件
环境变量配置文件
登陆时生效的环境变量配置文件(5个)
/etc/profile /etc/profile.d/*.sh /etc/bashrc #上面的对所有用户生效 下面的只对当前用户生效 ~/.bash_profile ~/.bashrc
`/etc/profile` ——> `~/.bash_profile` ——> `~/.bashrc` ——> `/etc/bashrc` ——> 命令提示符
|
|——> `/etc/profile.d/*.sh` ——> `/etc/profile.d/lang.sh` ——> `/etc/locale.conf`
非正常登录(使用 su 命令切换用户,子shell)
`/etc/bashrc` ——> 命令提示符
|
|——> `/etc/profile.d/*.sh` ——> `/etc/profile.d/lang.sh` ——> `/etc/locale.conf`
用户登陆过程先调用
/etc/profile
一些重要的变量就是在这个脚本文件中设置的,含义如下:
PATH: 预设可执行文件或命令的搜索路径。 USER: 用户登录时使用的用户名。 LOGNAME: 其值为$USER。 HOSTNAME: 所使用的主机名。 MAIL: 存放用户电子邮件的邮箱(实际上是一个ASCII码文件)。 HISTSIZE: 历史记录的行数。 INPUTRC: 存放的是针对键盘热键的信息(也是一个ASCII码文件)。
0x132 注销时生效的环境变量配置文件
用户再退出时,只会调用一个环境变量配置文件,就是~/.bash_logout。这个文件默认没有写入内容,比如,历史命令,备份某些数据。
0x133 其他配置文件
如~/bash_history文件。
0x134 Shell登陆信息
/etc/issue
本地登陆信息
我们再登陆tty1-tty6本地终端时,会有几行的欢迎界面。这些信息就在issue中
#cat /etc/issue
\S
Kernel \r on an \m
/l 显示第几个终端机接口 这个常用。
/m 显示硬件的等级(i386/i686...)
/n 显示主机的网络名称
/o 显示 domain name
/r 显示操作系统的版本/t 显示本地端时间的时间
/s 显示操作系统的名称
/v 显示操作系统的版本
/etc/issue.net
远程登陆信息
基本修改同上
但是
- 再/etc/issue中支持转义符,再/etc/issue.net不支持
- 其次ssh远程登陆还要由ssh的配置文件决定
ssh配置文件/etc/ssh/sshd_config
把Banner打开并输入配置文件目录效果
Banner /etc/issue.net
这样ssh远程登陆也可以显示欢迎信息,只是不再识别”\d”和”\l”等消息了
/etc/motd
登陆后 提示消息
如果由要写提示建议写 motd。