Linux(1):简介与系统安装:https://mp.csdn.net/postedit/88633915
Linux(2):常用命令:https://mp.csdn.net/postedit/88639718
鸟哥的Linux私房菜:https://wizardforcel.gitbooks.io/vbird-linux-basic-4e/content/86.html
目录
9 Shell基础
9.1 shell概述
9.1.1 shell概述
9.1.2 bash shell 的内置命令:type
9.2 shell的变量功能
9.2.1 什么是变量
9.2.2 变量的显示与设置:echo、unset
9.2.3 环境变量的功能(env、set、export)
9.2.4 影响显示结果的语系变量(locale)
9.2.5 变量的有效范围
9.2.6 变量键盘读取、数组与声明:read,array,declare
9.2.7 与文件系统及程序的限制关系:ulimit
9.2.8 变量内容的删除、替代与替换
9.3 脚本执行方式
9.3.1 echo
9.3.2 第一个脚本
9.4 别名与快捷键
9.4.1 别名
9.4.2 快捷键
9.5 历史命令
9.5.1 history
9.5.2 历史命令的调用
9.5.3 命令和文件补全
9.6 数据流重定向
9.6.1 标准输入输出
9.6.2 输出重定向
9.6.3 输入重定向(standard input : < 与 <<)
9.7 管道符
9.7.1 多命令顺序执行
9.7.2 管道符
9.8 通配符与特殊符号
9.8.1 通配符
9.8.2 Bash中其他特殊符号
9.9 Bash Shell 的操作环境
9.9.1 路径与命令查找顺序
9.9.2 bash 的登录与欢迎信息:/etc/issue,/etc/motd
9.9.3 bash 的环境配置文件
9.9.4 终端机的环境设置: stty, set
管理整个计算机硬件的其实是操作系统的内核(kernel),这个内核是需要被保护的,所以我们一般用户就只能通过shell来跟内核通信,以让内核达到我们线索想要达到的工作。我们必须要通过“shell”(内核)将我们输入的命令与内核通信,好让内核可以控制硬件来正确无误地工作。
Linux中的标准的默认的 shell 是 Bash 。
已进入系统就用到的shell就是父shell,可以用base命令,调用子shell。
type命令 用来显示指定命令的类型,判断给出的指令是内部指令还是外部指令。
命令类型:
语法:
type(选项)(参数)
选项:
-t:输出“file”、“alias”或者“builtin”,分别表示给定的指令为“外部指令”、“命令别名”或者“内部指令”;
-p:如果给出的指令为外部指令,则显示其绝对路径;
-a:在环境变量“PATH”指定的路径中,显示给定指令的信息,包括命令别名。
参数:
指令:要显示类型的指令。
通过 type 这个命令我们可以知道每个命令是否为 bash的内置命令。此外由于利用 type 找到后面的名称时,如果后面接的名称并不能以执行文件的状态被找到,那么该名称是不会被显示出来的。就是说type主要在找出“执行文件”而不是一般文件名。所以,这个 type 也可以用来作为类似 which命令 的用途了。
如果命令太长,可以使用 “\[enter]” 来将 [enter] 这个按键“转义”,让 [enter] 不再具有“开始执行”的功能,从而进行换行。如果顺利转义[enter] 后,下一行最前面就会出现>的符号,可以继续输入命令。
变量是以一组文字或者符号等,来替代一些设置或者是一串保留的数据。例如,我们每个账号的邮件信箱默认是以 MAIL 这个变量来进行访问的,当 dnteal 这个用户登录时,他便会取得 MAL 这个变量,而这个变量的内容其实就是var/spool/mail/dmtsai,那如果 vbird 登录呢?他取得的MAIL这个变量的内容其实就是 /var/spoonaiwbird 。而我们使用信件读取命令 mail 来读取自己的邮件信箱时,这个程序可以直接读取 MAIL 这个变量的内容,就能够自动分辨出属于自己的信箱信件了。
变量的显示可以使用 echo,只需要在变量名称前面加上$,或者以${变量}的方式显示都可以:
变量的设置规则:
1. 变量与内容以一个等号 [=] 来连接,如下所示:
[myname=VBird]
2. 等号两边不能直接接空格符,如下所示为错误:
[myname = VBird] 或 [myname=VBird Tsai]
3. 变量名称只能是英文字母与数字,但是开头字符不能是数字,如下为错误:
[2myname=VBird]
4. 变量内容若有空格符可使用双引号["]或单引号[']将变量内容结合起来,但
[var="lang is $LANG"] 则 [echo $var] 可得 [lang is zh_TW.UTF-8]
[var='lang is $LANG'] 则 [echo $var] 可得 [lang is $LANG]
5. 可用转义字符[ \ ]将特殊符号(如 [Enter],$,\,空格符,' 等)变成一般字符,如:
[myname=VBird\ Tsai]
6. 在一串指令的执行中,还需要通过其他的命令提供的信息时,可以使用反单引号 [`指令`] 或 [$(指令)] 。特别注意,那个 ` 是键盘上方的数字键 1 左边那个按键,而不是单引号!在一串命令中,在 ` 之内的命令将会被先执行,而其执行出来的结果将作为外部的输入信息。例如想要取得核心版本的设定:
[version=$(uname -r)] 再 [echo $version] 可得 [3.10.0-229.e17.x86_64]
7. 若该变量为了增加变量内容时,则可用 “$变量名称” 或 ${变量} 累加内容,如下所示:
[PATH="$PATH":/home/bin] 或 [PATH=${PATH}:/home/bin]
8. 若该变量需要在其他子程序执行,则需要以 export 来使变量变成环境变量:
[export PATH]
9. 通常大写字符为系统默认变量,自行设定变量可以使用小写字符,方便判断(纯粹依照使用者兴趣与嗜好);
10.取消变量的方法为使用 unset : [uset 变量名称] 例如取消 myname 的设定:
[unset myname]
例如:
① 如何让我刚才设置的name=VBird可以用在下个shell的程序?
[root@localhost ~]# name=VBird
[root@localhost ~]# bash <==进入到所谓的子进程
[root@localhost ~]# echo $name <==子进程:再次echo 一下;
<==结果是空的,并没有刚才设置的内容。
[root@localhost ~]# exit
[root@localhost ~]# export name
[root@localhost ~]# bash <==进入到所谓的子进程
[root@localhost ~]# echo $name <==子进程:在此执行
VBird <==看吧!出现设置值了
[root@localhost ~]# exit <==子进程:离开这个子进程
什么是“子进程”呢?就是说在我目前这个shell的情况下,去打开另一个新的shell,新那个shell就是子进程。在一般的状态下,父进程的自定义变量是无法在子进程内使用的。但是通过 export 将变量变成环境变量后,就能够在子进程下面应用了。
② 知何进入到你目前内核的模块目录?
[root@localhost ~]# cd /1ib/modules/"uname -r"/kernel
[root@localhost ~]# ed /1tb/aodulas/$(uname -r)/kornel
每个Unux都能够拥有多个内核版本,且几乎distribution的所有内核版本都不相同。
③ 每个crontab相关文件名的权限
(1)env
使用 env 列出目前的 shell 环境下的所有环境变量与其内容。env 是environment(环境)的缩写。
[root@localhost ~]# declare -i number=$RANDOM*10/32768;echo $number
8 <==此时会随机取出0~9之间的数值。
(2)set
用 set 观察所有变量 (含环境变量与自定义变量)
一般来说,不论是否为环境变量,只要跟我们目前这个 shell 的操作接口有关的变量,通常都会被设置为大写字符,也就是说,基本上,在Linux 默认的情况下,使用 {大写的字母} 来设置的变量一般为系统内定需要的变量。
一些较为重要的系统内定变量:
① PS1:(提示字符的配置)
这是 PS1 (数字的 1 不是英文字母),这个东西就是我们的“命令提示字符”。当我们每次按下 [Enter] 按键去运行某个命令后,最后要再次出现提示字符时, 就会主动去读取这个变量值了。上面 PS1 内显示的是一些特殊符号,这些特殊符号可以显示不同的信息, 每个 distributions 的 bash 默认的 PS1 变量内容可能有些许的差异,你可以用 man bash 去查询一下 PS1 的相关说明,以理解下面的一些符号意义。
例如:更改PS1变量的值
[root@www ~ ]# cd /home
[root@www home]# PS1='[\u@\h \w \A #\#]\$ '
[root@www /home 17:02 #85]#
② $:(关于本 shell 的 PID)
“$”本身也是个变量。这个代表的是『目前这个 Shell 的线程代号』,亦即是所谓的 PID (Process ID)。想要知道我们的 shell 的 PID ,就可以用: echo $$ 即可!出现的数字就是你的 PID 号码。
③ ?:(关于上个运行命令的回传值)
问号也是一个特殊的变量。 这个变量是:『上一个运行的命令所回传的值』, 上面这句话的重点是『上一个命令』与『回传值』两个地方。当我们运行某些命令时, 这些命令都会回传一个运行后的代码。一般来说,如果成功的运行该命令, 则会回传一个 0 值,如果运行过程发生错误,就会回传『错误代码』才对!一般就是以非为 0 的数值来取代。
例如:
[root@www ~]# echo $SHELL
/bin/bash <==可顺利显示!没有错误!
[root@www ~]# echo $?
0 <==因为没问题,所以回传值为 0
[root@www ~]# 12name=VBird
-bash: 12name=VBird: command not found <==发生错误了!bash回报有问题
[root@www ~]# echo $?
127 <==因为有问题,回传错误代码(非为0)
# 错误代码回传值依据软件而有不同,我们可以利用这个代码来搜寻错误的原因喔!
[root@www ~]# echo $?
0
# 咦!怎么又变成正确了?这是因为 "?" 只与『上一个运行命令』有关,
# 所以,我们上一个命令是运行『 echo $? 』,当然没有错误,所以是 0 没错!
④ OSTYPE, HOSTTYPE, MACHTYPE:(主机硬件与核心的等级)
目前个人计算机的 CPU 主要分为 32/64 位,其中 32 位又可分为 i386, i586, i686,而 64 位则称为 x86_64。 由于不同等级的 CPU 命令集不太相同,因此你的软件可能会针对某些 CPU 进行优化,以求取较佳的软件性能。你可以在 x86_64 的硬件上安装 i386 的 Linux 操作系统,但是你无法在 i686 的硬件上安装 x86_64 的 Linux 操作系统。
(3) export: 自定义变量转成环境变量
因为子进程仅会继承父进程的环境变量,子进程不会继承父进程的自定义变量,所以你原本 bash 中的自定义变量在进入了子进程之后就会消失不见,一直到你离开了子进程并回到原本的父进程后,这个变量才会又出现。如你想要让变量内容继续的在子程序中使用,那么可以用:
[root@www ~]# export 变量名称
如果仅执行 export 而没有接变量时,那么此时将会把所有的“环境变量”显示出来。
(1)查看Linux支持的语言:
(2)如何修订这些编码
当使用 locale 时,系统时列出目前Linux 主机内保有的语系文件,这些语系文件都放置在 /usr/lib/locale/ 这个目录中。
[root@www ~]# locale <==后面不加任何选项与参数即可!
LANG=en_US <==主语言的环境
LC_CTYPE="en_US" <==字符(文字)辨识的编码
LC_NUMERIC="en_US" <==数字系统的显示信息
LC_TIME="en_US" <==时间系统的显示数据
LC_COLLATE="en_US" <==字符串的比较与排序等
LC_MONETARY="en_US" <==币值格式的显示等
LC_MESSAGES="en_US" <==信息显示的内容,如菜单、错误信息等
LC_ALL= <==整体语系的环境
如果其他语系变量都未设置,且你有设置 LANG 或者是LC_ALL时,则其他的语系变量就会被这两个变量所替代。这也是为什么我们在 Linux 当中,通常说明仅设置 LANG 这个变量而已,因为它是最主要的设置变量。
默认的语系定义在:
[root@www ~]# cat /etc/sysconfig/i18n
LANG="zh_TW.UTF-8"
被 export 后的变量,我们可以称他为『环境变量』! 环境变量可以被子程序所引用,但是其他的自定义变量内容就不会存在于子程序中。
为什么环境变量的数据可以被子进程所引用呢?这是因为内存配置的关系。理论上是这样的:
通过这样的关系,我们就可以让某些安量在相关的进程之间存在,以帮助自己更方便地操作环境。不对要提醒的是,这个 “环境发量” 与 “bash的操作环境” 意思不大一样。举例来说,PS1并不是环境变量,但是过个PS1会影响到比bash的接口(提示符)。
(1)read
要读取来自键盘输入的变量,就是用 read 这个命令:
[root@www ~]# read [-pt] variable
选项与参数:
例如:
① 让用户由键盘输入一内容,将该内容变成名为 atest 的变量
[root@www ~]# read atest
This is a test <==此时光标会等待你输入!请输入左侧文字看看
[root@www ~]# echo $atest
This is a test <==你刚刚输入的数据已经变成一个变量内容!
② 提示使用者 30 秒内输入自己的大名,将该输入字符串作为名为 named 的变量内容
[root@www ~]# read -p "Please keyin your name: " -t 30 named
Please keyin your name: VBird Tsai <==注意看,会有提示字符喔!
[root@www ~]# echo $named
VBird Tsai <==输入的数据又变成一个变量的内容了!
(2)declare / typeset
declare 或 typeset 是一样的功能,就是声明量的类型。如果使用 declare 后面并没有接任何参数,那么 bash 就会主动将所有的变量名称与内容全部调出来,就好像使用 set 一样。
[root@www ~]# declare [-aixr] variable
选项与参数:
范例一:让变量 sum 进行 100+300+50 的加总结果
[root@www ~]# sum=100+300+50
[root@www ~]# echo $sum
100+300+50 <==咦!怎么没有帮我计算加总?因为这是文字型态的变量属性啊!
[root@www ~]# declare -i sum=100+300+50
[root@www ~]# echo $sum
[root@www ~]# 450
bash 对于变量有几个基本的定义:
如果不小心将变量设置为“只读”,通常得要注销再登录才能复原该变量的类型。
如果需要非字符串类型的变量,那就得要进行变量的声明才行。
范例二:将 sum 变成环境变量
[root@www ~]# declare -x sum
[root@www ~]# export | grep sum
declare -ix sum="450" <==果然出现了!包括有 i 与 x 的宣告!
范例三:让 sum 变成只读属性,不可更动!
[root@www ~]# declare -r sum
[root@www ~]# sum=tesgting
-bash: sum: readonly variable <==不能改这个变量了!
范例四:让 sum 变成非环境变量的自定义变量吧!
[root@www ~]# declare +x sum <== 将 - 变成 + 可以进行『取消』动作
[root@www ~]# declare -p sum <== -p 可以单独列出变量的类型
declare -ir sum="450" <== 只剩下 i, r 的类型,不具有 x
(3)数组 (array)
数组 (array) 变量类型,在bash中,数组的设置方式是:var[index] = content 。
我有一个数组名为 var ,而这个数组的内容为 var[1]=小明,var[2]=大明, var[3]=好明 .... 等等,那个 index 就是一些数字,重点是用中刮号 ([ ]) 来配置的。
范例:配置上面提到的 var[1] ~ var[3] 的变量。
[root@www ~]# var[1]="small min"
[root@www ~]# var[2]="big min"
[root@www ~]# var[3]="nice min"
[root@www ~]# echo "${var[1]}, ${var[2]}, ${var[3]}"
small min, big min, nice min
数组的变量类型比较有趣的地方在于“读取”,一般来说,建议直接以 ${数组} 的方式来读取,会比较正确无误。
Linux对于每个用户,系统限制其最大进程数。为提高性能,可以根据设备资源情况,设置各linux 用户的最大进程数。
ulimit主要是用来限制进程对资源的使用情况的,它支持各种类型的限制,常用的有:
ulimit使用的基本格式为:ulimit [options] [limit]
具体的options参数含义如下表所示:
选项 含义:
其中ulimit -n用于限制进程能够打开的文件描述符的最大数目。因为任何设备在linux下都是文件,通信的接口也有专门的接口文件负责,所以linux下进程tcp链接的最大并发量也受限于该值。
想要复解ulimit的设置最简单的方法就是注销再登录,否则就是得要重新以 ulimit 设置才行,不让要注意的是一般身份用户如果以ulimit设置了 -f 的文件大小,那么他只能继续减小文件容量,不能增加文件容量。
dd命令:
Linux dd命令用于读取、转换并输出数据。dd可从标准输入或文件中读取数据,根据指定的格式来转换数据,再输出到文件、设备或标准输出。
参数说明:
示例:
① 在Linux 下制作启动盘,可使用如下命令:
dd if=boot.img of=/dev/fd0 bs=1440k
② 将testfile文件中的所有英文字母转换为大写,然后转成为testfile_1文件,在命令提示符中使用如下命令:
dd if=testfile_2 of=testfile_1 conv=ucase
(1)变量内容的删除
范例一:先让小写的 path 自定义变量配置的与 PATH 内容相同
[root@www ~]# path=${PATH}
[root@www ~]# echo $path
/usr/kerberos/sbin:/usr/kerberos/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin
范例二:假设我不喜欢 kerberos,所以要将前两个目录删除掉,如何显示?
[root@www ~]# echo ${path#/*kerberos/bin:}
/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin
上面范例的重点如下:
${variable#/*kerberos/bin:}
上面的特殊字体部分是关键词!用在这种删除模式所必须存在的
${variable#/*kerberos/bin:}
这就是原本的变量名称,以上面范例二来说,这里就填写 path 这个『变量名称』!
${variable#/*kerberos/bin:}
这是重点!代表『从变量内容的最前面开始向右删除』,且仅删除最短的那个
${variable#/*kerberos/bin:}
代表要被删除的部分,由于 # 代表由前面开始删除,所以这里便由开始的 / 写起。
需要注意的是,我们还可以透过通配符 * 来取代 0 到无穷多个任意字符。
范例三:我想要删除前面所有的目录,仅保留最后一个目录
[root@www ~]# echo ${path#/*:}
/usr/kerberos/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin
# 由于一个 # 仅删除掉最短的那个,因此他删除的情况可以用底下的删除线来看: /usr/kerberos/sbin:/usr/kerberos/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin
[root@www ~]# echo ${path##/*:}
/root/bin
# 多加了一个 # 变成 ## 之后,他变成『删除掉最长的那个数据』。亦即是: /usr/kerberos/sbin:/usr/kerberos/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin
因为在 PATH 这个变量的内容中,每个目录都是以冒号“:”隔开的, 所以要从头删除掉目录就是介于斜线 (/) 到冒号 (:) 之间的数据!
但是 PATH 中不止一个冒号 (:) 啊! 所以 # 与 ## 就分别代表:
上面谈到的是从前面开始删除变量内容,那么如果想要从后面向前删除变量内容呢?这个时候就要用上百分比(%)符号了。如下。
范例四:想要删除最后面那个目录,亦即从 : 到 bin 为止的字符串
[root@www ~]# echo ${path%:*bin}
/usr/kerberos/sbin:/usr/kerberos/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
# 这个 % 符号代表由最后面开始向前删除!所以上面得到的结果其实是来自如下:/usr/kerberos/sbin:/usr/kerberos/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin
范例五:那如果我只想要保留第一个目录呢?
[root@www ~]# echo ${path%%:*bin}
/usr/kerberos/sbin
# 同样的, %% 代表的则是最长的符合字符串,所以结果其实是来自如下:/usr/kerberos/sbin:/usr/kerberos/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin
(2)变量内容的替换
范例六:将 path 的变量内容内的 sbin 取代成大写 SBIN:
[root@www ~]# echo ${path/sbin/SBIN}
/usr/kerberos/SBIN:/usr/kerberos/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin
# 关键词在于那两个斜线,两斜线中间的是旧字符串,后面的是新字符串,所以结果就会出现如上述的特殊字体部分。
[root@www ~]# echo ${path//sbin/SBIN}
/usr/kerberos/SBIN:/usr/kerberos/bin:/usr/local/SBIN:/usr/local/bin:/SBIN:/bin:
/usr/SBIN:/usr/bin:/root/bin
# 如果是两条斜线,那么就变成所有符合的内容都会被取代!
总结:
(3)变量的测试与内容替换
在某些时刻我们常常需要『判断』某个变量是否存在,若变量存在则使用既有的配置,若变量不存在则给予一个常用的配置。
我们举下面的例子来说明。
范例一:测试一下是否存在 username 这个变量,若不存在则给予 username 内容为 root
[root@www ~]# echo $username
<==由于出现空白,所以 username 可能不存在,也可能是空字符串
[root@www ~]# username=${username-root}
[root@www ~]# echo $username
root <==因为 username 没有配置,所以主动给予名为 root 的内容。
[root@www ~]# username="vbird tsai" <==主动配置 username 的内容
[root@www ~]# username=${username-root}
[root@www ~]# echo $username
vbird tsai <==因为 username 已经配置了,所以使用旧有的配置而不以 root 取代
在上面的范例中,重点在于减号“-”后面接的关键字。
new_var=${old_var-content}
新的变量,主要用来取代旧变量。新旧变量名称其实常常是一样的
new_var=${old_var-content}
这是本范例中的关键词部分!必须要存在的哩!
new_var=${old_var-content}
旧的变量,被测试的项目!
new_var=${old_var-content}
变量的『内容』,在本范例中,这个部分是在『给予未配置变量的内容』
不过这还是有点问题!因为 username 可能已经被配置为『空字符串』了!果真如此的话,那你还可以使用底下的范例来给予 username 的内容成为 root !
范例二:若 username 未配置或为空字符串,则将 username 内容配置为 root
[root@www ~]# username=""
[root@www ~]# username=${username-root}
[root@www ~]# echo $username
<==因为 username 被配置为空字符串了!所以当然还是保留为空字符串!
[root@www ~]# username=${username:-root}
[root@www ~]# echo $username
root <==加上“:”后若变量内容为空或者是未配置,都能够以后面的内容替换!
测试:先假设 str 不存在 (用 unset) ,然后测试一下等号 (=) 的用法:
[root@www ~]# unset str; var=${str=newvar}
[root@www ~]# echo var="$var", str="$str"
var=newvar, str=newvar <==因为 str 不存在,所以 var/str 均为 newvar
测试:如果 str 已存在了,测试一下 var 会变怎样?
[root@www ~]# str="oldvar"; var=${str=newvar}
[root@www ~]# echo var="$var", str="$str"
var=oldvar, str=oldvar <==因为 str 存在,所以 var 等于 str 的内容
如果旧变量不存在,整个测试旧告诉我“有错误”,此时就能够使用问好“?”,如下所示。
测试:若 str 不存在时,则 var 的测试结果直接显示 "无此变量"
[root@www ~]# unset str; var=${str?无此变量}
-bash: str: 无此变量 <==因为 str 不存在,所以输出错误信息
测试:若 str 存在时,则 var 的内容会与 str 相同!
[root@www ~]# str="oldvar"; var=${str?novar}
[root@www ~]# echo var="$var", str="$str"
var=oldvar, str=oldvar <==因为 str 存在,所以 var 等于 str 的内容
echo命令的功能是在显示器上显示一段文字,一般起到一个提示的作用。
该命令的一般格式为:
echo [-ne][字符串]或 echo [--help][--version]
其中选项n表示输出文字后不换行;字符串能加引号,也能不加引号。用echo命令输出加引号的字符串时,将字符串原样输出;用echo命令输出不加引号的字符串时,将字符串中的各个单词作为字符串输出,各字符串之间用一个空格分割。
补充说明:echo会将输入的字符串送往标准输出。输出的字符串间以空白字符隔开, 并在最后加上换行号。
参 数:
\\ 插入\字符;
echo支持修改颜色。
变量的显示:echo。变量的显示能利用echo读出,只是需要在变量名称前面加上$,或者是以${变量}的方式来显示都可以。
在脚本中第一行要写 #!/bin/bash ,以说明接下来的是标准的Linux shell脚本。
执行脚本的方法:
如下图所示。
命令执行时输入命令太长时,利用“\[Enter]”来换行。
Linux的标准shell是Bash。
如何知道目前有哪些的命令别名呢?就使用 alias :
也可使用alias进行修改:
修改是临时修改的,重启系统就会失效。
对每个用户单独生效。
通过source .bashrc可立即生效。
unalias也是临时删除,永久删除也需要修改 ~/.bashrc。
/bin/ls 为绝对路径,直接用该命令来执行; ls 为命令别名:alias ls='ls --color=auto'。
[root@www ~]# history [n]
[root@www ~]# history [-c]
[root@www ~]# history [-raw] histfiles
选项与参数:
范例一:列出目前内存内的所有 history 记忆
[root@www ~]# history
# 前面省略
1017 man bash
1018 ll
1019 history
1020 history
# 列出的信息当中,共分两栏,第一栏为该命令在这个 shell 当中的代码,另一个则是命令本身的内容喔!至于会显示几笔命令记录,则与 HISTSIZE 有关!
范例二:列出目前最近的 3 笔数据
[root@www ~]# history 3
1019 history
1020 history
1021 history 3
范例三:立刻将目前的数据写入 histfile 当中
[root@www ~]# history -w
# 在默认的情况下,会将历史纪录写入 ~/.bash_history 当中!
[root@www ~]# echo $HISTSIZE
1000
在正常的情况下,历史命令的读取与记录是这样的:
当我们以 bash 登陆 Linux 主机之后,系统会主动的由家目录的 ~/.bash_history 读取以前曾经下过的命令,那么 ~/.bash_history 会记录几笔数据呢?这就与你 bash 的 HISTFILESIZE 这个变量配置值有关了!
假设我这次登陆主机后,共下达过 100 次命令,『等我注销时, 系统就会将 101~1100 这总共 1000 笔历史命令升级到 ~/.bash_history 当中。』 也就是说,历史命令在我注销时,会将最近的 HISTFILESIZE 笔记录到我的纪录文件当中啦!当然,也可以用 history -w 强制立刻写入的!那为何用『升级』两个字呢? 因为 ~/.bash_history 记录的笔数永远都是 HISTFILESIZE 那么多,旧的信息会被主动的拿掉! 仅保留最新的!
vi /etc/profile
~/.bash_history 记录的是前一次登录以前所执行过的命令,而至于这一次登录所执行的命令都被暂存在临时内存中,当你成功注销系统后,该命令记忆才会记录到.bash_history中。
那么 history 这个历史命令只可以让我查询命令而已吗?当然不止,。 我们可以利用相关的功能来帮我们运行命令!
[root@www ~]# !number
[root@www ~]# !command
[root@www ~]# !!
选项与参数:
number :运行第几笔命令的意思;
command :由最近的命令向前搜寻『命令串开头为 command』的那个命令,并运行;
!! :就是运行上一个命令(相当于按↑按键后,按 Enter)
[root@www ~]# history
66 man rm
67 alias
68 man history
69 history
[root@www ~]# !66 <==运行第 66 笔命令
[root@www ~]# !! <==运行上一个命令,本例中亦即 !66
[root@www ~]# !al <==运行最近以 al 为开头的命令(上头列出的第 67 个)
系统命令的补全也依赖于$PATH环境变量。这个按键的功能就是在bash里面才有的。
命令与文件补全功能([Tab]按键的好处)
经常在bash环境中使用[Tab]是个很好的习惯,因为至少可以让你少打很多字,并且确定输入的数据是正确的。使用[Tab]按键的时机依据[Tab]接在命令后或参数后而有所不同。
所以说,如果我想要知道我的环境中所有可以执行的命令有几个,就直接在bash的提示符后面连续按两次[Tab]按键就能够显示所有的可执行命令了。那如果想要知道系统当中所有以c为开头的命令呢?就按下“c[Tab][Tab]”就好。
数据流重导向 (redirect) 由字面上的意思来看,好像就是将“数据给他传导到其他地方去”的样子? 没错~数据流重导向就是将某个指令执行后应该要出现在屏幕上的数据, 给他传输到其他的地方,例如文件或者是设备 (例如打印机之类的)!这在 Linux 的文字模式下面可重要的! 尤其是如果我们想要将某些数据储存下来时,就更有用了!
一般来说,如果你要执行一个指令,通常他会是这样的:
图1 指令执行过程的数据传输情况
我们执行一个指令的时候,这个指令可能会由文件读入数据,经过处理之后,再将数据输出到屏幕上。 在上图当中, standard output 与 standard error output 分别代表“标准输出 (STDOUT)”与“标准错误输出 (STDERR)”, 这两个默认都是输出到屏幕上面来的。
standard output 与 standard error output
简单的说,标准输出指的是“指令执行所回传的正确的讯息”,而标准错误输出可理解为“ 指令执行失败后,所回传的错误讯息”。举个简单例子来说,我们的系统默认有 /etc/crontab 但却无 /etc/vbirdsay, 此时若下达“ cat /etc/crontab /etc/vbirdsay ”这个指令时,cat 会进行:
在Linux中,一切皆文件。
不管正确或错误的数据都是默认输出到屏幕上,所以屏幕当然是乱乱的!那能不能通过某些机制将这两股数据分开呢? 当然可以!那就是数据流重导向的功能啊!数据流重导向可以将 standard output (简称 stdout) 与 standard error output (简称 stderr) 分别传送到其他的文件或设备去,而分别传送所用的特殊字符则如下所示:
要注意,“ 1>> ”以及“ 2>> ”中间是没有空格的。
Windows和Linux中都有定时任务。
此时错误输出时,大于号的右边没有空格。
例如:
(1)如果想要将正确的与错误的数据分别存入不同的文件中需要怎么做?
范例:将 stdout 与 stderr 分存到不同的文件去
[dmtsai@study ~]$ find /home -name .bashrc > list_right 2> list_error
(2)/dev/null 垃圾桶黑洞设备与特殊写法
/dev/null 可以吃掉任何导向这个设备的信息,结果不显示在屏幕,也不保存在文件里:
范例四:承范例三,将错误的数据丢弃,屏幕上显示正确的数据
[dmtsai@study ~]$ find /home -name .bashrc 2> /dev/null
/home/dmtsai/.bashrc <==只有 stdout 会显示到屏幕上, stderr 被丢弃了
(3)要将正确与错误数据通通写入同一个文件去呢?
范例五:将指令的数据全部写入名为 list 的文件中
[dmtsai@study ~]$ find /home -name .bashrc > list 2> list <==错误
[dmtsai@study ~]$ find /home -name .bashrc > list 2>&1 <==正确
[dmtsai@study ~]$ find /home -name .bashrc &> list <==正确
上述表格第一行错误的原因是,由于两股数据同时写入一个文件,又没有使用特殊的语法, 此时两股数据可能会交叉写入该文件内,造成次序的错乱。所以虽然最终 list 文件还是会产生,但是里面的数据排列就会怪怪的,而不是原本屏幕上的输出排序。 至于写入同一个文件的特殊语法如上表所示,你可以使用 2>&1 也可以使用 &> 。
为何要使用命令输出重导向呢?
执行wc命令后,点“Ctrl+D”退出输入。
行数、单词数、字符数。
软件安装打补丁时可能会用到输入重定向。
以最简单的说法来说,“<” 就是“将原本需要由键盘输入的数据,改由文件内容来取代”的意思。
cat:
cat命令是linux下的一个文本输出命令,通常是用于观看某个文件的内容的;
cat主要有三大功能:
cat具体命令格式为 : cat [-AbeEnstTuv] [--help] [--version] fileName
参数说明:
示例:
清空 /etc/test.txt 文档内容:
cat /dev/null > /etc/test.txt
cat 也可以用来制作镜像文件。例如要制作软盘的镜像文件,将软盘放好后输入:
cat /dev/fd0 > OUTFILE
相反的,如果想把 image file 写到软盘,输入:
cat IMG_FILE > /dev/fd0
注:
然后由下面的 cat 指令操作来了解一下什么叫做“键盘输入”:
范例六:利用 cat 指令来创建一个文件的简单流程
[dmtsai@study ~]$ cat > catfile
testing
cat file test
<==这里按下 [ctrl]+d 来离开
[dmtsai@study ~]$ cat catfile
testing
cat file test
由于加入 > 在 cat 后,所以那个 catfile 会被主动的创建,而内容就是刚刚键盘上面输入的那两行数据了。
能不能用纯文本文件取代键盘的输入,也就是说,用某个文件的内容来取代键盘的敲击呢? 如下所示:
范例七:用 stdin 取代键盘的输入以创建新文件的简单流程
[dmtsai@study ~]$ cat > catfile < ~/.bashrc
[dmtsai@study ~]$ ll catfile ~/.bashrc
-rw-r--r--. 1 dmtsai dmtsai 231 Mar 6 06:06 /home/dmtsai/.bashrc
-rw-rw-r--. 1 dmtsai dmtsai 231 Jul 9 18:58 catfile
# 注意看,这两个文件的大小会一模一样!几乎像是使用 cp 来复制一般!
<< 这个连续两个小于的符号,代表的是“结束的输入字符”的意思。举例来讲:“我要用 cat 直接将输入的讯息输出到 catfile 中, 且当由键盘输入 eof 时,该次输入就结束”,那我可以这样做:
[dmtsai@study ~]$ cat > catfile << "eof"
> This is a test.
> OK now stop
> eof <==输入这关键字,立刻就结束而不需要输入 [ctrl]+d
[dmtsai@study ~]$ cat catfile
This is a test.
OK now stop <==只有这两行,不会存在关键字那一行!
利用 << 右侧的控制字符,我们可以终止一次输入, 而不必输入 [crtl]+d 来结束。
(1)cmd ; cmd (不考虑指令相关性的连续指令下达)
在指令与指令中间利用分号 (;) 来隔开,这样一来,分号前的指令执行完后就会立刻接着执行后面的指令了。
简单地检测命令是否正确执行。
(2)$? (指令回传值) 与 && 或 ||
如同上面谈到的,两个指令之间有相依性,而这个相依性主要判断的地方就在于前一个指令执行的结果是否正确。 指令回传值,“若前一个指令执行的结果为正确,在 Linux 下面会回传一个 $? = 0 的值”。 那么我们怎么通过这个回传值来判断后续的指令是否要执行呢?这就得要借由“ && ”及“ || ”的帮忙了! 注意喔,两个 & 之间是没有空格的!那个 | 则是 [Shift]+[] 的按键结果。
例如:我不清楚 /tmp/abc 是否存在,但就是要创建 /tmp/abc/hehe 文件
[dmtsai@study ~]$ ls /tmp/abc || mkdir /tmp/abc && touch /tmp/abc/hehe
上面这个范例总是会尝试创建 /tmp/abc/hehe 的喔!不论 /tmp/abc 是否存在。 由于Linux 下面的指令都是由左往右执行的,所以范例三有几种结果我们来分析一下:
整个流程图示如下:
图 指令依序执行的关系示意图
例题:以 ls 测试 /tmp/vbirding 是否存在,若存在则显示 "exist" ,若不存在,则显示 "not exist"!这又牵涉到逻辑判断的问题,如果存在就显示某个数据,若不存在就显示其他数据,那我可以这样做:
ls /tmp/vbirding && echo "exist" || echo "not exist"
由于指令是一个接着一个去执行的,因此,如果真要使用判断, 那么这个 && 与 || 的顺序就不能搞错。一般来说,假设判断式有三个,也就是:
command1 && command2 || command3
而且顺序通常不会变,因为一般来说, command2 与 command3 会放置肯定可以执行成功的指令
不能将&&与|| 弄反,应该先写逻辑与,再写逻辑或:
就如同前面所说的, bash 命令执行的时候有输出的数据会出现! 那么如果这群数据必需要经过几道手续之后才能得到我们所想要的格式,应该如何来设置? 这就牵涉到管线命令的问题了 (pipe) ,管线命令使用的是“ | ”这个界定符号! 另外,管线命令与“连续下达命令”是不一样的! 下面我们先举一个例子来说明一下简单的管线命令。
假设我们想要知道 /etc/ 下面有多少文件,那么可以利用 ls /etc 来查阅,不过, 因为 /etc 下面的文件太多,导致一口气就将屏幕塞满了~不知道前面输出的内容是啥?此时,我们可以通过 less 指令的协助,利用:
[root@localhost ~]# ls -al /etc | less
如此一来,使用 ls 指令输出后的内容,就能够被 less 读取,并且利用 less 的功能,我们就能够前后翻动相关的信息了。我们就来了解一下这个管线命令“ | ”的用途吧! 其实这个管线命令“ | ”仅能处理经由前面一个指令传来的正确信息,也就是 standard output 的信息,对于 stdandard error 并没有直接处理的能力。那么整体的管线命令可以使用下图表示:
图 管线命令的处理示意图
在每个管线后面接的第一个数据必定是“指令”喔!而且这个指令必须要能够接受 standard input 的数据才行,这样的指令才可以是为“管线命令”,例如 less, more, head, tail 等都是可以接受 standard input 的管线命令啦。至于例如 ls, cp, mv 等就不是管线命令了!因为 ls, cp, mv 并不会接受来自 stdin 的数据。 也就是说,管线命令主要有两个比较需要注意的地方:
如果要让 standard error 可以被管线命令所使用,那该如何处理?其实就是通过上一小节的数据流重导向。
(1)选取命令: cut, grep
一般来说,选取讯息通常是针对“一行一行”来分析的, 并不是整篇讯息分析的喔~下面我们介绍两个很常用的讯息选取命令:
① cut:
[dmtsai@study ~]$ cut -d '分隔字符' -f fields <==用于有特定分隔字符
[dmtsai@study ~]$ cut -c 字符区间 <==用于排列整齐的讯息
选项与参数:
例如:将 export 输出的讯息,取得第 12 字符以后的所有字串
[dmtsai@study ~]$ export | cut -c 12-
HISTCONTROL="ignoredups"
HISTSIZE="1000"
HOME="/home/dmtsai"
HOSTNAME="study.centos.vbird"
.....(其他省略).....
# 知道怎么回事了吧?用 -c 可以处理比较具有格式的输出数据!
# 我们还可以指定某个范围的值,例如第 12-20 的字符,就是 cut -c 12-20 等等!
cut 在处理多空格相连的数据时,可能会比较吃力一点,所以某些时刻可能会使用 awk 来取代!
② grep
刚刚的 cut 是将一行讯息当中,取出某部分我们想要的,而 grep 则是分析一行讯息, 若当中有我们所需要的信息,就将该行拿出来~简单的语法是这样的:
[dmtsai@study ~]$ grep [-acinv] [--color=auto] '搜寻字串' filename
选项与参数:
范例:在 last 的输出讯息中,只要有 root 就取出,并且仅取第一列
CentOS 7 当中,默认的 grep 已经主动加上 --color=auto 在 alias 内了!
(2)排序命令: sort, wc, uniq
下面我们介绍几个好用的排序与统计指令:
① sort
sort 是很有趣的指令,他可以帮我们进行排序,而且可以依据不同的数据类型来排序喔! 例如数字与文字的排序就不一样。此外,排序的字符与语系的编码有关,因此, 如果您需要排序时,建议使用 LANG=C 来让语系统一,数据排序比较好一些。[dmtsai@study ~]$ sort [-fbMnrtuk] [file or stdin]
选项与参数:
示例:
范例:/etc/passwd 内容是以 : 来分隔的,我想以第三栏来排序,该如何?
[dmtsai@study ~]$ cat /etc/passwd | sort -t ':' -k 3
root:x:0:0:root:/root:/bin/bash
dmtsai:x:1000:1000:dmtsai:/home/dmtsai:/bin/bash
alex:x:1001:1002::/home/alex:/bin/bash
arod:x:1002:1003::/home/arod:/bin/bash
# 看到特殊字体的输出部分了吧?怎么会这样排列啊?
# 如果是以文字体态来排序的话,原本就会是这样,想要使用数字排序:
# cat /etc/passwd | sort -t ':' -k 3 -n
# 这样才行啊!用那个 -n 来告知 sort 以数字来排序啊!
范例:利用 last ,将输出的数据仅取帐号,并加以排序
[dmtsai@study ~]$ last | cut -d ' ' -f1 | sort
② uniq
如果我排序完成了,想要将重复的数据仅列出一个显示,可以怎么做呢?
[dmtsai@study ~]$ uniq [-ic]
选项与参数:
使用 last 将帐号列出,仅取出帐号栏,进行排序,还想要知道每个人的登陆总次数
[root@localhost ~]# last | cut -d ' ' -f 1 | sort | uniq -c
1
9 reboot
20 root
1 wtmp
③ wc
如果我想要知道 /etc/man_db.conf 这个文件里面有多少字?多少行?多少字符的话, 可以怎么做呢?其实可以利用 wc 这个指令来达成喔!他可以帮我们计算输出的讯息的整体数据。
[dmtsai@study ~]$ wc [-lwm]
选项与参数:
范例:我知道使用 last 可以输出登陆者,但是 last 最后两行并非帐号内容,那么请问,我该如何以一行指令串取得登陆系统的总人次?
[root@localhost ~]# last |grep [a-zA-Z] | grep -v 'wtmp' | wc -l
29
# 由于 last 会输出空白行, wtmp, unknown, reboot 等无关帐号登陆的信息,因此,我利用
# grep 取出非空白行,以及去除上述关键字那几行,再计算行数,就能够了解啰!
(3)双向重定向: tee
我们由前一节知道 > 会将数据流整个传送给文件或设备,因此我们除非去读取该文件或设备, 否则就无法继续利用这个数据流。万一我想要将这个数据流的处理过程中将某段讯息存下来,应该怎么做? 利用 tee 就可以~我们可以这样简单的看一下:
图 tee 的工作流程示意图
tee 会同时将数据流分送到文件去与屏幕 (screen);而输出到屏幕的,其实就是 stdout ,那就可以让下个指令继续处理喔!
[dmtsai@study ~]$ tee [-a] file
选项与参数:
例如:让我们将 last 的输出存一份到 last.list 文件中,并在屏幕显示第一列;
(4)字符转换命令: tr, col, join, paste, expand
① tr
我们在 vim 程序编辑器当中,提到过 DOS 断行字符与 Unix 断行字符的不同,并且可以使用 dos2unix 与 unix2dos 来完成转换。
tr 可以用来删除一段讯息当中的文字,或者是进行文字讯息的替换!
[dmtsai@study ~]$ tr [-ds] SET1 ...
选项与参数:
范例:将 /etc/passwd 转存成 dos 断行到 /root/passwd 中,再将 ^M 符号删除
[dmtsai@study ~]$ cp /etc/passwd ~/passwd && unix2dos ~/passwd
[dmtsai@study ~]$ file /etc/passwd ~/passwd
/etc/passwd: ASCII text
/home/dmtsai/passwd: ASCII text, with CRLF line terminators <==就是 DOS 断行
[dmtsai@study ~]$ cat ~/passwd | tr -d '\r' > ~/passwd.linux
# 那个 \r 指的是 DOS 的断行字符,关于更多的字符,请参考 man tr
[dmtsai@study ~]$ ll /etc/passwd ~/passwd*
-rw-r--r--. 1 root root 2092 Jun 17 00:20 /etc/passwd
-rw-r--r--. 1 dmtsai dmtsai 2133 Jul 9 22:13 /home/dmtsai/passwd
-rw-rw-r--. 1 dmtsai dmtsai 2092 Jul 9 22:13 /home/dmtsai/passwd.linux
# 处理过后,发现文件大小与原本的 /etc/passwd 就一致了!
② col
[dmtsai@study ~]$ col [-xb]
选项与参数:
范例一:利用 cat -A 显示出所有特殊按键,最后以 col 将 [tab] 转成空白
[dmtsai@study ~]$ cat -A /etc/man_db.conf <==此时会看到很多 ^I 的符号,那就是 tab
[dmtsai@study ~]$ cat /etc/man_db.conf | col -x | cat -A | more
# 嘿嘿!如此一来, [tab] 按键会被取代成为空白键,输出就美观多了!
虽然 col 有他特殊的用途,不过,很多时候,他可以用来简单的处理将 [tab] 按键取代成为空白键! 例如上面的例子当中,如果使用 cat -A 则 [tab] 会以 ^I 来表示。 但经过 col -x 的处理,则会将 [tab] 取代成为对等的空白键!
③ join
join 看字面上的意义 (加入/参加) 就可以知道,他是在处理两个文件之间的数据, 而且,主要是在处理“两个文件当中,有 "相同数据" 的那一行,才将他加在一起”的意思。
[dmtsai@study ~]$ join [-ti12] file1 file2
选项与参数:
我们利用下面的简单例子来说明:
我们知道 /etc/passwd 第四个字段是 GID ,那个 GID 记录在
/etc/group 当中的第三个字段,请问如何将两个文件整合?
[root@study ~]# join -t ':' -1 4 /etc/passwd -2 3 /etc/group | head -n 3
0:root:x:0:root:/root:/bin/bash:root:x:
1:bin:x:1:bin:/bin:/sbin/nologin:bin:x:
2:daemon:x:2:daemon:/sbin:/sbin/nologin:daemon:x:
# 同样的,相同的字段部分被移动到最前面了!所以第二个文件的内容就没再显示。
需要特别注意的是,在使用 join 之前,你所需要处理的文件应该要事先经过排序 (sort) 处理! 否则有些比对的项目会被略过!
④ paste
这个 paste 就要比 join 简单多了!相对于 join 必须要比对两个文件的数据相关性, paste 就直接“将两行贴在一起,且中间以 [tab] 键隔开”而已!简单的使用方法:
[dmtsai@study ~]$ paste [-d] file1 file2
选项与参数:
例如:用 root 身份,先将 /etc/group 读出(用 cat),然后将 /etc/passwd 与 /etc/shadow 同一行贴在一起:
⑤ expand
就是在将 [tab] 按键转成空白键啦~可以这样玩:
[dmtsai@study ~]$ expand [-t] file
选项与参数:
将 /etc/man_db.conf 内行首为 MANPATH 的字样就取出;仅取前三行;将所有的符号都列出来;将 [tab] 按键设置成 6 个字符
[dmtsai@study ~]$ grep '^MANPATH' /etc/man_db.conf | head -n 3 | expand -t 6 - | cat -A
MANPATH_MAP /bin /usr/share/man$
MANPATH_MAP /usr/bin /usr/share/man$
MANPATH_MAP /sbin /usr/share/man$
123456123456123456123456123456123456123456123456...
# 仔细看一下上面的数字说明,因为我是以 6 个字符来代表一个 [tab] 的长度,所以,MAN... 到 /usr 之间
会隔 12 (两个 [tab]) 个字符喔!如果 tab 改成 9 的话,情况就又不同了!
此外,您也可以参考一下 unexpand 这个将空白转成 [tab] 的指令功能。
(5)切割命令: split
如果你有文件太大,导致一些携带式设备无法复制的问题,找 split 就对了! 他可以帮你将一个大文件,依据文件大小或行数来分区,就可以将大文件分区成为小文件了!
[dmtsai@study ~]$ split [-bl] file PREFIX
选项与参数:
范例一:我的 /etc/services 有六百多K,若想要分成 300K 一个文件时?
[dmtsai@study ~]$ cd /tmp; split -b 300k /etc/services services
[dmtsai@study tmp]$ ll -k services*
-rw-rw-r--. 1 dmtsai dmtsai 307200 Jul 9 22:52 servicesaa
-rw-rw-r--. 1 dmtsai dmtsai 307200 Jul 9 22:52 servicesab
-rw-rw-r--. 1 dmtsai dmtsai 55893 Jul 9 22:52 servicesac
# 那个文件名可以随意取的啦!我们只要写上前导文字,小文件就会以xxxaa, xxxab, xxxac 等方式来创建小文件的!
范例二:如何将上面的三个小文件合成一个文件,文件名为 servicesback
[dmtsai@study tmp]$ cat services* >> servicesback
# 就用数据流重导向就好啦!
范例三:使用 ls -al / 输出的信息中,每十行记录成一个文件
[dmtsai@study tmp]$ ls -al / | split -l 10 - lsroot
[dmtsai@study tmp]$ wc -l lsroot*
10 lsrootaa
10 lsrootab
4 lsrootac
24 total
# 重点在那个 - 啦!一般来说,如果需要 stdout/stdin 时,但偏偏又没有文件,
# 有的只是 - 时,那么那个 - 就会被当成 stdin 或 stdout ~
(6)参数代换: xargs
xargs 是在做什么的呢?就以字面上的意义来看, x 是加减乘除的乘号,args 则是 arguments (参数) 的意思,所以说,这个玩意儿就是在产生某个指令的参数的意思! xargs 可以读入 stdin 的数据,并且以空白字符或断行字符作为分辨,将 stdin 的数据分隔成为 arguments 。 因为是以空白字符作为分隔,所以,如果有一些文件名或者是其他意义的名词内含有空白字符的时候, xargs 可能就会误判了。
[dmtsai@study ~]$ xargs [-0epn] command
选项与参数:
当 xargs 后面没有接任何的指令时,默认是以 echo 来进行输出喔!
例如:将所有的 /etc/passwd 内的账号都以finger查询,但一次查询5个账户
这个 -p 的选项可以让使用者的使用过程中,被询问到每个指令是否执行!
finger命令可以让使用者查询一些其他使用者的资料。会列出来的资料有:
其中 .plan、.project 和 .forward 就是使用者在他的 Home Directory 里的 .plan , .project 和 .forward 等档案里的资料。如果没有就没有。finger 指令并不限定于在同一服务器上查询,也可以寻找某一个远端服务器上的使用者。只要给一个像是 E-mail address 一般的地址即可。
使用权限:所有使用者。
语法:
finger [options] user[@address]
参数说明:
会使用 xargs 的原因是, 很多指令其实并不支持管线命令,因此我们可以通过 xargs 来提供该指令引用 standard input 之用!
范例四:找出 /usr/sbin 下面具有特殊权限的文件名,并使用 ls -l 列出详细属性
[dmtsai@study ~]$ find /usr/sbin -perm +7000 | xargs ls -l
-rwx--s--x. 1 root lock 11208 Jun 10 2014 /usr/sbin/lockdev
-rwsr-xr-x. 1 root root 113400 Mar 6 12:17 /usr/sbin/mount.nfs
-rwxr-sr-x. 1 root root 11208 Mar 6 11:05 /usr/sbin/netreport
.....(下面省略).....
# 应该会想到使用“ ls -l $(find /usr/sbin -perm /7000) ”来处理这个范例
(7)关于减号 - 的用途
管线命令在 bash 的连续的处理程序中是相当重要的!另外,在 log file 的分析当中也是相当重要的一环, 所以请特别留意!另外,在管线命令当中,常常会使用到前一个指令的 stdout 作为这次的 stdin , 某些指令需要用到文件名称 (例如 tar) 来进行处理时,该 stdin 与 stdout 可以利用减号 "-" 来替代, 举例来说:
上面这个例子是说:“我将 /home 里面的文件给他打包,但打包的数据不是纪录到文件,而是传送到 stdout; 经过管线后,将 tar -cvf - /home 传送给后面的 tar -xvf - ”。后面的这个 - 则是取用前一个指令的 stdout, 因此,我们就不需要使用 filename 了!
more 是用来查看文件中的内容,分屏显示。
使用管道符,命令2一定要能操作命令1。
netstat -a:查看系统中所有的网络连接。
LISTEN:这个端口被监听,等待有人访问; ESTABLISHED:有人正在连接。
一般查找目录。
以上为 bash 环境中常见的特殊符号汇整!理论上,你的“文件名”尽量不要使用到上述的字符!
反引号:在键盘1旁边。
bash的登录和欢迎信息设置。
issue内的各代码的意义:
1、/etc/issue 本地登陆显示的信息,本地登录前
2、/etc/issue.net 网络登陆显示的信息,登录后显示,需要由sshd配置
3、/etc/motd 常用于通告信息,如计划关机时间的警告等,登陆后的提示信息
至于文件 /etc/motd,(motd即motd即message of today布告栏信息的缩写) 则是在每次用户登录时,motd文件的内容会显示在用户的终端。系统管理员可以在文件中编辑系统活动消息,例如:管理员通知用户系统何时进行软件或硬件的升级、何时进行系统维护等。如果shell支持中文,还可以使用中文,这样看起来更易于了解。/etc/motd缺点是,现在许多用户登录系统时选择自动进入图形界面,所以这些信息往往看不到。
issue与motd文件主要区别在于:当一个用户过本地文本设备(如本地终端,本地虚拟控制台等)登录 /etc/issue 的文件内容显示在login提示符之前,而 /etc/motd 内容显示在用户成功登录系统之后。
issue.net文件(只针对网络用户)--若通过远程本文设备(如通过ssh或telnet等)登录,则显示该文件的内容。使用ssh登录时,会不会显示issue信息由sshd服务的sshd_config的Banner属性配置决定。
其中上面的三个文件,issue.net和motd文件都是在登录后显示,那么顺序是怎么样的呢,如下图所示:
在这里使用的是Putty进行登录,我们可以发现先显示的是issue.net文件中的内容,最后才显示motd文件中的内容。又使用Xshell 进行登录,得出的结果一样、都是先显示issue.net文件内容,最后显示motd文件的内容。中间隔着上次登录信息。
其中不同的是:
在Linux中系统有一些环境配置文件,让bash在启动是直接读取这些配置文件,以规划好bash的操作环境。配置文件可分为全体的配置文件以及用户个人偏好配置文件。
一、login 与 non-login shell
介绍 login 和 non-login shell 是因为这两个取得 bash 的情况下,读取的配置文件数据并不一样所致。
(1)login shell
我们先来谈谈 login shell 。一般来说 login shell 会读取两个配置文件:
① /etc/profile(login shell 才会读)
可以使用 vim 去阅读这个文件的内容,这个配置文件可以利用使用者的标识符(UID)来决定很多重要的变量数据,这也是每个使用者登入取得 bash 时一定会读取的文件,所以如果你想要帮所有者设定整体环境,可以改这里。不过,没事还是不要随便改这个文件,这个文件设定的有其他重要变量,也会引用其他文件。例如,/etc/profile.d/*.sh、/etc/local.conf等等。
这个文件设置的变量主要有:
/etc/profile 可不止会做这些事而已,他还会去调用外部的设置数据!在 CentOS 5.x 默认的情况下,下面这些数据会依序的被调用进来:
其实这个文件并没有被执行。/etc/profle会主动判断用户有没有自定义输入的按键功能,如果没有的话,/etc/protile 就会决定设置“INPUTRC=/etc/inputrc”这个变量。此文件内容为bash 的热键、[Tab]有没有声音等的数据。
其实这是个目录内的众多文件!只要在 /etc/profile.d/ 这个目录内且扩展名为 .sh ,另外,使用者能够具有 r 的权限, 那么该文件就会被 /etc/profile 调用进来。在 CentOS 5.x 中,这个目录下面的文件规范了 bash 操作接口的颜色、 语系、ll 与 ls 指令的命令别名、vi 的命令别名、which 的命令别名等等。如果你需要帮所有使用者设置一些共享的命令别名时, 可以在这个目录下面自行创建扩展名为 .sh 的文件,并将所需要的数据写入即可!
这个文件是由/etc/prolle.d/lang.sh调用的。这也是我们决定bash 默认使用何种语系的重要配置文件。文件里最重要的就是 LANG/LC_ALL 这些个变量的设置。bash 的 login shell 情况下所读取的整体环境配置文件其实只有/etc/profile, 但是/etc/profile还会调用其他的配置文件,所以让我们的bash操作接口变得非常的友善。
② ~/.bash_profile(login shell 才会读)
bash 在读完整体环境设定的 /etc/profile 并藉此呼叫其他配置文件后,接下来则是会读取使用者的个人配置文件。在login shell 的 bash 环境中,所读取的个人偏好配置文件其实主要有三个,依顺序分别为:
其实 bash 的 login shell 设定只会读取上面三个文件的其中一个,而读取的顺序则是依照上面的顺序。 如果 ~/.bash_profile 不存在才会去读取 ~/.bash_login,而前两者都不存在才会读取 ~/.profile 的意思。 会有这么多的文件,其实是因应其他 shell 转换过来的使用者的习惯而已。
最后,看看这个 login shell 的读取流程:
实线的方向是主线程流程,虚线的方向则是被调用的配置文件。
source :读入环境配置文件的指令
由于 /etc/profile 与 ~/.bash_profile 都是在取得 login shell 的时候才会读取的配置文件,所以, 如果你将自己的偏好设置写入上述的文件后,通常都是得登出再登陆后,该设置才会生效。那么,能不能直接读取配置文件而不登出登陆呢? 可以的!那就得要利用 source 这个指令了!
[root@localhost ~]# source 配置文件文件名
范例:将主文件夹的 ~/.bashrc 的设置读入目前的 bash 环境中
[dmtsai@study ~]$ source ~/.bashrc <==下面这两个指令是一样的!
[dmtsai@study ~]$ . ~/.bashrc
利用 source 或小数点 (.) 都可以将配置文件的内容读进来目前的 shell 环境中! 举例来说,我修改了 ~/.bashrc ,那么不需要登出,立即以 source ~/.bashrc 就可以将刚刚最新设置的内容读进来目前的环境中!还有,包括 ~/bash_profile 以及 /etc/profile 的设置中, 很多时候也都是利用到这个 source (或小数点)的功能!
有没有可能会使用到不同环境配置文件的时候?有啊! 最常发生在一个人的工作环境分为多种情况的时候了!举个例子来说,在鸟哥的大型主机中, 常常需要负责两到三个不同的案子,每个案子所需要处理的环境变量订定并不相同, 那么鸟哥就将这两三个案子分别编写属于该案子的环境变量设置文件,当需要该环境时,就直接“ source 变量文件 ”,如此一来,环境变量的设置就变的更简便而灵活了!
(2)non-login shell
谈完了 login shell 后,那么 non-login shell 这种非登陆情况取得 bash 操作接口的环境配置文件又是什么? 当你取得 non-login shell 时,该 bash 配置文件仅会读取 ~/.bashrc 而已!那么默认的 ~/.bashrc 内容是如何?
[root@study ~]# cat ~/.bashrc
# .bashrc
# User specific aliases and functions
alias rm='rm -i' <==使用者的个人设置
alias cp='cp -i'
alias mv='mv -i'
# Source global definitions
if [ -f /etc/bashrc ]; then <==整体的环境设置
. /etc/bashrc
fi
特别注意一下,由于 root 的身份与一般使用者不同。以 root 的身份登录和一般使用者的 ~/.bashrc 会有些许不同。看一下,你会发现在 root 的 ~/.bashrc 中其实已经规范了较为保险的命令别名了。 此外,咱们的 CentOS 5.x 还会主动的调用 /etc/bashrc 这个文件喔!为什么需要调用 /etc/bashrc 呢? 因为 /etc/bashrc 帮我们的 bash 定义出下面的数据:
你要注意的是,这个 /etc/bashrc 是 CentOS 特有的 (其实是 Red Hat 系统特有的),其他不同的 distributions 可能会放置在不同的文件名就是了。由于这个 ~/.bashrc 会调用 /etc/bashrc 及 /etc/profile.d/*.sh , 所以,万一你没有 ~/.bashrc (可能自己不小心将他删除了),那么你会发现你的 bash 提示字符可能会变成这个样子:
-bash-4.2$
不要太担心啦!这是正常的,因为你并没有调用 /etc/bashrc 来规范 PS1 变量啦!而且这样的情况也不会影响你的 bash 使用。 如果你想要将命令提示字符捉回来,那么可以复制 /etc/skel/.bashrc 到你的主文件夹,再修订一下你所想要的内容, 并使用 source 去调用 ~/.bashrc ,那你的命令提示字符就会回来啦!
二、其他相关的配置文件
事实上还有一些配置文件可能会影响到你的 bash 操作的,下面就来谈一谈:
这个文件乍看之下好像跟 bash 没相关性,但是对于系统管理员来说, 却也是很重要的一个文件!这文件的内容“规范了使用 man 的时候, man page 的路径到哪里去寻找!”所以说的简单一点,这个文件规定了下达 man 的时候,该去哪里查看数据的路径设置!
那么什么时候要来修改这个文件呢?如果你是以 tarball 的方式来安装你的数据,那么你的 man page 可能会放置在 /usr/local/softpackage/man 里头,那个 softpackage 是你的套件名称, 这个时候你就得以手动的方式将该路径加到 /etc/man_db.conf 里头,否则使用 man 的时候就会找不到相关的说明文档。
还记得我们在历史命令提到过这个文件吧?默认的情况下, 我们的历史命令就记录在这里!而这个文件能够记录几笔数据,则与 HISTFILESIZE 这个变量有关。每次登陆 bash 后,bash 会先读取这个文件,将所有的历史指令读入内存, 因此,当我们登陆 bash 后就可以查知上次使用过哪些指令。
这个文件则记录了“当我登出 bash 后,系统再帮我做完什么动作后才离开”的意思。 你可以去读取一下这个文件的内容,默认的情况下,登出时, bash 只是帮我们清掉屏幕的讯息而已。 不过,你也可以将一些备份或者是其他你认为重要的工作写在这个文件中 (例如清空暂存盘), 那么当你离开 Linux 的时候,就可以解决一些烦人的事情!
(1)stty
如何查阅目前的一些按键内容呢?可以利用 stty (setting tty 终端机的意思) 呢! stty 也可以帮助设置终端机的输入按键代表意义!
[dmtsai@study ~]$ stty [-a]
选项与参数:
-a :将目前所有的 stty 参数列出来;
范例一:列出所有的按键与按键内容
[dmtsai@study ~]$ stty -a
speed 38400 baud; rows 20; columns 90; line = 0;
intr = ^C; quit = ^\; erase = ^?; kill = ^U; eof = ^D; eol = <undef>; eol2 = <undef>;
swtch = <undef>; start = ^Q; stop = ^S; susp = ^Z; rprnt = ^R; werase = ^W; lnext = ^V;
flush = ^O; min = 1; time = 0;
....(以下省略)....
我们可以利用 stty -a 来列出目前环境中所有的按键列表,在上头的列表当中,需要注意的是特殊字体那几个, 此外,如果出现 ^ 表示 [Ctrl] 那个按键的意思。举例来说, intr = ^C 表示利用 [ctrl] + c 来达成的。几个重要的代表意义是:
(2)set
除了 stty 之外,其实我们的 bash 还有自己的一些终端机设置值呢!那就是利用 set 来设置的! 我们之前提到一些变量时,可以利用 set 来显示,除此之外,其实 set 还可以帮我们设置整个指令输出/输入的环境。 例如记录历史命令、显示错误内容等等。
[dmtsai@study ~]$ set [-uvCHhmBx]
选项与参数:
范例一:显示目前所有的 set 设置值
[dmtsai@study ~]$ echo $-
himBH
# 那个 $- 变量内容就是 set 的所有设置啦! bash 默认是 himBH 喔!
范例二:设置 "若使用未定义变量时,则显示错误讯息"
[dmtsai@study ~]$ set -u
[dmtsai@study ~]$ echo $vbirding
-bash: vbirding: unbound variable
# 默认情况下,未设置/未宣告 的变量都会是“空的”,不过,若设置 -u 参数,
# 那么当使用未设置的变量时,就会有问题啦!很多的 shell 都默认启用 -u 参数。
# 若要取消这个参数,输入 set +u 即可!
范例三:执行前,显示该指令内容。
[dmtsai@study ~]$ set -x
++ printf '\033]0;%s@%s:%s\007' dmtsai study '~' # 这个是在列出提示字符的控制码!
[dmtsai@study ~]$ echo ${HOME}
+ echo /home/dmtsai
/home/dmtsai
++ printf '\033]0;%s@%s:%s\007' dmtsai study '~'
# 看见否?要输出的指令都会先被打印到屏幕上喔!前面会多出 + 的符号!
另外,其实我们还有其他的按键设置功能呢!就是在前一小节提到的 /etc/inputrc 这个文件里面设置。 还有例如 /etc/DIRCOLORS 与 /usr/share/terminfo/ 等,也都是与终端机有关的环境设置文件呢!
我们将 bash 默认的组合键给他汇整如下: