第1关:内置命令之alias
任务描述
本关将带领大家熟悉 bash 的内置命令,并掌握一些常用的内置命令。 在开启此小节之前,相信你已经对 shell 编程的变量和字符串的使用有了一定的了解。需注意: 本课程没有描述 shell 数组的概念,因为在实际的操作中 shell 数组并不是很友好,一般在数据处理的模型都用 python 来代替 shell,如果大家对 shell 数组感兴趣,请同学们可以自行翻阅资料了解一下 shell 的数组概念。
相关知识
什么是内建命令
所谓 Shell 内建命令,就是由 Bash 自身提供的命令,而不是文件系统中的某个可执行文件。 例如,用于进入或者切换目录的 cd 命令,虽然我们一直在使用它,但如果不加以注意,很难意识到它与普通命令的性质是不一样的:该命令并不是某个外部文件,只要在 Shell 中你就可以运行这个命令。 可以使用 type
来确定一个命令是否是内建命令:
root@Test-old-web01:/opt/f89vxyw7/task1# type cd
cd is a shell builtin
root@Test-old-web01:/opt/f89vxyw7/task1# type ifconfig
ifconfig is /sbin/ifconfig
由此可见,cd 是一个 Shell 内建命令,而 ifconfig 是一个外部文件,它的位置是/sbin/ifconfig
。 还记得系统变量 $PATH
吗?$PATH
变量包含的目录中几乎聚集了系统中绝大多数的可执行命令,它们都是外部命令。
通常来说,内建命令会比外部命令执行得更快,执行外部命令时不但会触发磁盘 I/O,还需要 fork 出一个单独的进程来执行,执行完成后再退出。而执行内建命令相当于调用当前 Shell 进程的一个函数。
shell有哪些内建命令
下表列出了 Bash Shell 中直接可用的内建命令。
命令 说明
: 扩展参数列表,执行重定向操作
. 读取并执行指定文件中的命令(在当前 shell 环境中)
alias 为指定命令定义一个别名
bg 将作业以后台模式运行
bind 将键盘序列绑定到一个 readline 函数或宏
break 退出 for、while、select 或 until 循环
builtin 执行指定的 shell 内建命令
caller 返回活动子函数调用的上下文
cd 将当前目录切换为指定的目录
command 执行指定的命令,无需进行通常的 shell 查找
compgen 为指定单词生成可能的补全匹配
complete 显示指定的单词是如何补全的
compopt 修改指定单词的补全选项
continue 继续执行 for、while、select 或 until 循环的下一次迭代
declare 声明一个变量或变量类型。
dirs 显示当前存储目录的列表
disown 从进程作业表中刪除指定的作业
echo 将指定字符串输出到 STDOUT
enable 启用或禁用指定的内建shell命令
eval 将指定的参数拼接成一个命令,然后执行该命令
exec 用指定命令替换 shell 进程
exit 强制 shell 以指定的退出状态码退出
export 设置子 shell 进程可用的变量
fc 从历史记录中选择命令列表
fg 将作业以前台模式运行
getopts 分析指定的位置参数
hash 查找并记住指定命令的全路径名
help 显示帮助文件
history 显示命令历史记录
jobs 列出活动作业
kill 向指定的进程 ID(PID) 发送一个系统信号
let 计算一个数学表达式中的每个参数
local 在函数中创建一个作用域受限的变量
logout 退出登录 shell
mapfile 从 STDIN 读取数据行,并将其加入索引数组
popd 从目录栈中删除记录
printf 使用格式化字符串显示文本
pushd 向目录栈添加一个目录
pwd 显示当前工作目录的路径名
read 从 STDIN 读取一行数据并将其赋给一个变量
readarray 从 STDIN 读取数据行并将其放入索引数组
readonly 从 STDIN 读取一行数据并将其赋给一个不可修改的变量
return 强制函数以某个值退出,这个值可以被调用脚本提取
set 设置并显示环境变量的值和 shell 属性
shift 将位置参数依次向下降一个位置
shopt 打开/关闭控制 shell 可选行为的变量值
source 读取并执行指定文件中的命令(在当前 shell 环境中)
suspend 暂停 Shell 的执行,直到收到一个 SIGCONT 信号
test 基于指定条件返回退出状态码 0 或 1
times 显示累计的用户和系统时间
trap 如果收到了指定的系统信号,执行指定的命令
type 显示指定的单词如果作为命令将会如何被解释
typeset 声明一个变量或变量类型。
ulimit 为系统用户设置指定的资源的上限
umask 为新建的文件和目录设置默认权限
unalias 刪除指定的别名
unset 刪除指定的环境变量或 shell 属性
wait 等待指定的进程完成,并返回退出状态码
常用的内建命令
一下子掌握所有的内建命令难度要求比较大,我们可以从常用内建命令入手,第一个内置命令: alias
。 1、alias alias 用来给命令创建一个别名。若直接输入该命令且不带任何参数,则列出当前 Shell 进程中使用了哪些别名,如下:
root@Test-old-web01:/opt/f89vxyw7/task1# alias
alias egrep='egrep --color=auto'
alias fgrep='fgrep --color=auto'
alias grep='grep --color=auto'
alias l='ls -CF'
alias la='ls -A'a
alias ll='ls -alF'
alias ls='ls --color=auto'
现在你应该能理解类似ll
这样的命令为什么与ls -l
或者 ls -alF
的效果是一样的吧,是因为ls -alF
被重新命名为ll
。因此,在命令行输入 ll
,即相当于输入了 ls -alF
。
使用 alias 命令自定义别名的语法格式为(临时):
alias new_name='command'
通过 date 命令可以获得当前的 UNIX 时间戳,具体写法为 date +%s
,如果你嫌弃它太长或者不容易记住,那可以给它定义一个别名。
alias timestamp='date +%s'
这样你在命令行输入 timestamp
获得的效果及跟输入date +%s
一样,如下:
root@Test-old-web01:/opt/f89vxyw7/task1# date +%s
1580972143
root@Test-old-web01:/opt/f89vxyw7/task1# alias timestamp='date +%s'
root@Test-old-web01:/opt/f89vxyw7/task1# timestamp
1580972158
注意:通过以上方式命令别名后,在退出当前窗口后,刚设定的 alias 命令别名也就消失了,如何才能永久使用了?请看下面的介绍:
首先,如果想让别名能够在不同的 shell 会话中使用,就需要把它们添加到 shell 用来保存别名的文件中。大多数情况下,这个文件不是 .bashrc
,就是 .bash_aliases
,我们使用的系统 CentOS,是保存在.bashrc
里。(或者可以在 root 家目录下输入:ls -a ~
看到那个文件)
如果要永久保存,就把alias new_name='command'
给编辑到 /root/.bashrc
下,然后:wq
保存退出,但得重新加载别名文件,才能生效,可执行 source ~/.bashrc
(这样更改后只有 root 用户的别名生效,要想普通用户有效,普通用户目录下的.bashrc
也必需作同样的修改!比如现在有用户为 jerry,则需要到其/home/jerry/.bashrc
下编辑然后执行source ~/.bashrc
)。
##pdl用户登录,在/home/pdl加目录下 或者 "~"及代表用户的家目录
## /home/pdl/.bashrc 某行添加
## alias homeview='ll ~'
##添加
pdl@Test-old-web01:~$ vim /home/pdl/.bashrc
##重新加载别名文件
pdl@Test-old-web01:~$ source ~/.bashrc
##执行homeview 即相当于 执行 ll ~
pdl@Test-old-web01:~$ homeview
total 36
drwx------ 4 pdl pdl 4096 Feb 6 15:10 ./
drwxr-xr-x 5 root root 4096 Dec 30 11:18 ../
-rw------- 1 pdl pdl 1114 Nov 21 16:54 .bash_history
-rw-r--r-- 1 pdl pdl 220 Sep 1 2015 .bash_logout
-rw-r--r-- 1 pdl pdl 3795 Feb 6 15:10 .bashrc
drwx------ 2 pdl pdl 4096 Aug 22 09:00 .cache/
-rw-r--r-- 1 pdl pdl 655 May 16 2017 .profile
drwx------ 2 pdl pdl 4096 Aug 22 15:11 .ssh/
-rw------- 1 pdl pdl 1016 Feb 6 15:10 .viminfo
##退出终端重新加载,发现别名homeview永久存在
实际用例:假设生产环境有三台机器127.1.1.2
;127.1.1.3
;127.1.1.4
; 你可以通过 alias 的方式简化 ssh 登录方式,操作如下: 在~/.bashrc
下末尾行追加内容。然后 source ~/.bashrc
,这样即可以在命令行直接输入 ssh_01,ssh_02,ssh_03
快速登陆。
alias ssh_01= 'sshpass -p 密码 ssh -o StrictHostKeyChecking=no -p 22 root@127.1.1.2'
alias ssh_02= 'sshpass -p pass2 ssh -o StrictHostKeyChecking=no -p 22 root@127.1.1.3'
alias ssh_03= 'sshpass -p pass4 ssh -o StrictHostKeyChecking=no -p 22 root@127.1.1.4'
实践要求
本关没有评测,希望大家独立在命令行按照示例自己操作一遍,了解熟悉 shell 的内置命令,并掌握 alias 的使用方式以及应用场景。
开始你的任务吧,祝你成功!
第2关:内置命令之echo,read
任务描述
本关继续为大家介绍 shell 的内置命令 echo 和 read,通过学习掌握 echo 和 read 的用法。
相关知识
内置命令——echo
echo 是一个 Shell 内建命令,用来在终端输出字符串,并在最后默认加上换行符。请看下面的例子:
#!/bin/bash
name="在线编程"
url="www.educoder.net"
echo "小哥哥,小姐姐,你好!" #直接输出字符串
echo $url #输出变量
echo "${name}的网址是:${url}" #双引号包围的字符串中可以解析变量
echo '${name}的网址是:${url}' #单引号包围的字符串中不能解析变量
输出结果为:
[root@pre-host-work02 opt]# bash a.sh
小哥哥,小姐姐,你好!
www.educoder.net
在线编程的网址是:www.educoder.net
echo 命令输出结束后默认会换行,如果不希望换行,可以加上-n
参数,如下所示:
#!/bin/bash
name="在线编程"
url="www.educoder.net"
echo -n "小哥哥,小姐姐,你好!" #直接输出字符串
echo -n $url #输出变量
echo "${name}的网址是:${url}" #双引号包围的字符串中可以解析变量
输出结果为:
[root@pre-host-work02 opt]# bash a.sh
小哥哥,小姐姐,你好!www.educoder.net在线编程的网址是:www.educoder.net
默认情况下,echo 不会解析以反斜杠\
开头的转义字符。比如,\n
表示换行,echo 默认会将它作为普通字符对待。请看下面的例子:
[root@localhost ~]# echo "hello \nworld"
hello \nworld
我们可以添加-e
参数来让 echo 命令解析转义字符。例如:
[root@localhost ~]# echo -e "hello \nworld"
hello
world
内置变量——read
read 是 Shell 内置命令,用来从标准输入中读取数据并赋值给变量。如果没有进行重定向,默认就是从键盘读取用户输入的数据;如果进行了重定向,那么可以从文件中读取数据(后续我们会在 shell 的输入和输出中深入讲解重定向的概念,不了解的同学可以不用理会,暂时就认为:read 命令就是从键盘读取数据)。
read 命令的用法为:
read [-options] [variables]
options 表示选项,如下表所示;variables 表示用来存储数据的变量,可以有一个,也可以有多个。
options 和 variables 都是可选的,如果没有提供变量名,那么读取的数据将存放到环境变量 REPLY 中。 Shell read 命令支持的选项:
【实例1】使用 read 命令给多个变量赋值,并打印提示语 read -p
。
#!/bin/bash
read -p "Enter some information > " name age
echo "网站名字:$name"
echo "年龄:$age"
输出结果为:
[root@pre-host-work02 opt]# bash a.sh
Enter some information > educoder 20
网站名字:educoder
年龄:20
Tips: 如果用 read 交互参数,输入错了,请按住Ctrl+Backspace清除而不是只按住Backspace。
【示例2】只读取一个字符。
#!/bin/bash
read -n 1 -p "Enter a char > " char
printf "\n" #换行
echo $char
运行结果:
Enter a char > 1
1
【实例3】在指定时间内输入密码。
#!/bin/bash
if
read -t 20 -sp "Enter password in 20 seconds(once) > " pass1 && printf "\n" && #第一次输入密码
read -t 20 -sp "Enter password in 20 seconds(again)> " pass2 && printf "\n" && #第二次输入密码
[ $pass1 == $pass2 ] #判断两次输入的密码是否相等
then
echo "Valid password"
else
echo "Invalid password"
fi
这段代码中,我们使用**&&**组合了多个命令,相当于其他语言中的 and ,这些命令会依次执行,并且从整体上作为 if 语句的判断条件。只要其中一个命令执行失败(退出状态为非 0 值),整个判断条件就失败了,后续的命令也就没有必要执行了。
如果两次输入密码相同,运行结果为:
Enter password in 20 seconds(once) >
Enter password in 20 seconds(again)>
Valid password
如果两次输入密码不同,运行结果为:
Enter password in 20 seconds(once) >
Enter password in 20 seconds(again)>
Invalid password
如果第一次输入超时,运行结果为:
Enter password in 20 seconds(once) > Invalid password
如果第二次输入超时,运行结果为:
Enter password in 20 seconds(once) >
Enter password in 20 seconds(again)> Invalid password
关于 echo 和 read 的使用方式还有很多,大家可以通过 help echo 和 help read 的方式去获取更多的帮助文档。
编程要求
请根据提示,补全下面编辑器 Begin-End 区间的代码。
#********* Begin *********#
##1.请用echo输出变量 var var2 ,期待输出结果为 “hello www.educoder.net" 后面没有换行符号 无需补全
##2.结合之前shell字符串的学习,请截取var2,从左边第5个字符开始,截取的字符个数为8,将截取的值赋值给变量Var3
##参照第一题,用echo 输出 var Var3,后面没有换行符
开始你的任务吧,祝你成功!
第3关:内置命令之exit、declare
任务描述
本关继续带领大家了解掌握 shell 的内置命令,接下来将会学习内置命令exit
和declare
。
相关知识
内置命令 —— exit
exit 是一个 Shell 内置命令,用来退出当前 Shell 进程,并返回一个退出状态;使用**$?**可以接收这个退出状态,$?
如果不记得是什么,请查看前一章节的shell变量。exit
命令可以接受一个整数值作为参数,代表退出状态。如果不指定,默认状态值是 0。
一般情况下,退出状态为 0 表示成功,退出状态为非 0 表示执行失败(出错)了, exit
退出状态只能是一个介于 0~255 之间的整数,其中只有 0 表示成功,其它值都表示失败。
Shell 进程执行出错时,可以根据退出状态来判断具体出现了什么错误,比如打开一个文件时,我们可以指定 1 表示文件不存在,2 表示文件没有读取权限,3 表示文件类型不对。 【实列1】运行该脚本:
#!/bin/bash
echo "befor exit"
exit 8
echo "after exit
[root@localhost ~]$ bash ./test.sh
befor exit
可以看到,"after exit"并没有输出,这说明遇到 exit 命令后,test.sh 执行就结束了。 注意:exit 表示退出当前 Shell 进程,我们必须在新进程中运行 test.sh,否则当前 Shell 会话(终端窗口)会被关闭,我们就无法看到输出结果了。 我们可以紧接着使用$?
来获取 test.sh 的退出状态:
[root@localhost ~]$ echo $?
8
内置命令 —— declare
declare
一般很少用到,但大家要知道下列常用的方法。
【实列2】declare 将变量声明为整数并进行计算。
#!/bin/bash
declare -i m n ret #将多个变量声明为整数
m=10
n=30
ret=$m+$n
echo $ret
如果我们不使用 declare,结果如下所示:
[root@pre-host-work02 ~]# a=10
[root@pre-host-work02 ~]# b=20
[root@pre-host-work02 ~]# c=$a+$b
[root@pre-host-work02 ~]# echo $c
10+20
因此注意在 shell 如果要求整数值的话,不要忘了有 declare 这样的内置命令来定义变量。关于 declare 的其他使用方式,大家可以自行去了解。
编程要求
完成指定功能,具体要求如下:
1.现有变量 a、b、c ,已知 a 为整数 100,b 为整数 300,c=$a+$b
,打印 c 的值,应该为 400; 2.补全[ $? -eq ]内的值,-eq 的意思是‘等于’,注意 [ ] 两边要留一个空格,通过 $? 判断上面的命令是否运行成功,如果运行成功则输出success
,否则输出 faild
。
开始你的任务吧,祝你成功!