认识与学习 BASH

认识 BASH 这个 Shell

从标题就可以知道,BASH 是个 Shell,那什么是Shell呢?

硬件、核心与 Shell

我们通过 Shell 将我们输入的指令与 Kernel 沟通,让 Kernel 可以 控制硬件来正确工作。Shell 就是接受用户指令,然后将指令发送给Kernel的应用程序。

系统的合法 shell 与 /etc/shells 功能

Linux 中默认的shell 为bash(Bourne Again SHell),Linux 支持的 shell 记录在/etc/shells 中:

[root@centos764 ~]# cat /etc/shells
/bin/sh
/bin/bash
/sbin/nologin
/usr/bin/sh
/usr/bin/bash
/usr/sbin/nologin
/bin/tcsh
/bin/csh

Linux 用户登录时会获取一个预设的shell, 这个 shell 记录在 /etc/passwd 中有记录(最后一个字段)。

Shell 的变量功能

  • Linux 是多人多任务的环境,每个人登入系统都能取得一个 bash shell。
  • 变量就是以一组文字或符号等,来取代 一些设定或者是一串保留的数据

变量的取用与设定

输出变量的内容命令为 echo,格式如下:

[dmtsai@study ~]$ echo $PATH 
[dmtsai@study ~]$ echo ${PATH}  # 推荐这种方式

在 bash 当中,当一个变量名称尚未被设定时,预设的内容是空的。

变量的设定方法及格式如下:

  • 变量与变量内容以一个等号 = 来连结,等号两边不能直接接空格符,例 myname=zzz
  • 变量名称只能是英文字母与数字,但是开头字符不能是数字
  • 可用转义字符 \ 将特殊符号(如 [Enter], $, \, 空格符, '等)变成一般字符,例 myname=\$
  • 在一串指令的执行中,还需要由其他额外的指令所提供的信息时,可以使用反单引号 `指令`$(指 令)。 例 version=`uname -r`version=$(uname -r)
  • 若该变量为扩增变量内容时,则可用 "$变量名称" 或${变量} 累加内容,例 PATH="$PATH":/home/binPATH=${PATH}:/home/bin
  • 若该变量需要在其他子程序执行,则需要以 export 来使变量变成环境变量,例 export PATH
  • 取消变量的方法为使用 unset,格式为: unset 变量名称 ,例 unset myname

可以将变量追加到 ~/.bashrc 文件中永久存储变量名及内容。

查看环境变量的命令

查看环境变量的常用命令: env , set , export

  • env 列出目前 shell 环境中的所有环境变量及其内容
  • set 列出系统中已经存在的shell变量(包括环境变量和自定义变量),以及设置 shell 变量的新变量值
  • export 不接参数时列出所有所有环境变量,接自定义变量时将自定义变量转成环境变量。子程序会继承父程序的环境变量,也就是说:环境变量会被子程序所继承,自定义变量不会被子程序继承

比较特殊的有:

  • PS1:(提示字符的设定) 就是我们的 命令提示字符 ,其代表含义为 admin@centos764 (在我系统上)
  • $:(当前使用 shell 的 PID)
  • ?:(上个执行指令的回传值) 当执行某些指令时,这些指令都会回传一个执行后的代码。一般来说,如果成功的执行该指令, 则会回传一个 0 值,如果执行过程发生错误,就会回传错误代码

影响显示结果的语系变量 (locale)

使用 locale -a 命令列出Linux 支持的语系。 直接使用 locale 命令会列出当前所有关于语系设置的环境变量值,当设置了 LANG 或 LC_ALl 时,其他的语系变量就会被这两个变量取代。 语系文件存放在 /usr/lib/locale/ 这个目录下,语系的配置文件在 /etc/locale.conf 文件中。

从键盘读取变量与宣告(declare)

通过 read 命令从键盘读取字符设置变量,read 命令格式:

[dmtsai@study ~]$ read [-pt] variable 
选项与参数: 
-p  :后面可以接提示字符 
-t  :后面可以接等待的秒数

范例:

zzz@Ubuntu:~$ read -p "input your name: " -t 20 YOURNAME
input your name: zzz
zzz@Ubuntu:~$ echo ${YOURNAME}
zzz

通过 declaretypeset 宣告变量的类型,declare 命令格式:

[dmtsai@study ~]$ declare [-aixr] variable 
选项与参数: 
-a  :将后面名为 variable 的变量定义成为数组 (array) 类型 
-i  :将后面名为 variable 的变量定义成为整数数字 (integer) 类型 
-x  :用法与 export 一样,就是将后面的 variable 变成环境变量; 
-r  :将变量设定成为 readonly 类型,该变量不可被更改内容,也不能 unset 
不加任何参数,其效果与 set 命令一样

范例:将 YAMOURNE 设置为环境变量 declare -x YOURNAME

值得注意的是这些命令生成的环境变量没有写进文件,所以注销后这些环境变量都会消失,永久保存环境变量需要将其写入文件。如果写入 /etc/profile 文件则对所有用户有效,写入 ~/.bashrc仅对当前用户有效。

与文件系统及程序的限制关系: ulimit

bash 是可以限制用户的某些系统资源,包括可以开启的文件数量, 可使用的 CPU 时间,可以使用的内存总量等等。通过 ulimit 命令设置:

[dmtsai@study ~]$ ulimit [-SHacdfltu] [配额] 
选项与参数: 
-H  :hard limit ,严格的设定,必定不能超过这个设定的数值; 
-S  :soft limit ,警告的设定,可以超过这个设定值,但是若超过则有警告讯息。 
-a  :后面不接任何选项与参数,可列出所有的限制额度; 
-c  :当某些程序发生错误时,系统可能会将该程序在内存中的信息写成文件(除错用),       这种文件就被称为核心文件(core file)。此为限制每个核心文件的最大容量。 
-f  :此 shell 可以建立的最大文件容量(一般可能设定为 2GB)单位为 Kbytes 
-d  :程序可使用的最大断裂内存(segment)容量; 
-l  :可用于锁定 (lock) 的内存量 
-t  :可使用的最大 CPU 时间 (单位为秒) 
-u  :单一用户可以使用的最大程序(process)数量。 

范例:

[admin@centos764 ~]$ ulimit -a
core file size          (blocks, -c) 0              # 只要是 0 就代表没限制 
data seg size           (kbytes, -d) unlimited 
scheduling priority             (-e) 0
file size               (blocks, -f) unlimited      # 可建立的单一文件的大小
pending signals                 (-i) 7152
max locked memory       (kbytes, -l) 64
max memory size         (kbytes, -m) unlimited
open files                      (-n) 1024           # 同时可开启的文件数量 
pipe size            (512 bytes, -p) 8
POSIX message queues     (bytes, -q) 819200
real-time priority              (-r) 0
stack size              (kbytes, -s) 8192
cpu time               (seconds, -t) unlimited
max user processes              (-u) 4096
virtual memory          (kbytes, -v) unlimited
file locks                      (-x) unlimited

要复原 ulimit 的设定最简单的方法就是注销再登入,否则就是得要重新以 ulimit 设 定才行。

命令别名与历史命令

使用 alias 设置命令别名,一般直接写入文件 ~/.bashrc ,命令格式为 alias aliasname='command -parameter'

history 命令会显示当前 bash 用过的命令(存放在~/.bash_history),可以用 history -w 强制立即写入该文件内。 用 history -c 清除该文件内容。

Bash Shell 的操作环境

路径与指令搜寻顺序

下达命令后,命令的搜索执行的顺序:

  1. 以相对/绝对路径执行指令,例如 /bin/ls./ls
  2. 由 alias 找到该指令来执行
  3. 由 bash 内建的 (builtin) 指令来执行
  4. 透过 $PATH 这个变量的顺序搜寻到的第一个指令来执行

bash 的进站与欢迎消息: /etc/issue, /etc/motd

例如登录阿里云服务器会显示 Welcome to Alibaba Cloud Elastic Compute Service !,这个是写在 /etc/motd 中的,而版本信息一般写在 /etc/issue 文件中。

bash 的环境配置文件

系统有一些环境配置文件的存在,让 bash 在启动时直接读取这些配置文件,以规划好 bash 的操作环境,配置文件又可以分为全体系统的配置文件以及用户个人偏好配置文件。命令别名、自定义的变量,在注销 bash 后就会失效,所以你想要保留你的设定,就得要将这些设定写入配置文件(~/.bashrc等)。

login shell 取得 bash 时需要完整的登入流程的,就称为 login shell。如由 tty1 ~ tty6 登入, 需要输入用户的账号与密码。 non-login shell:取得 bash 接口的方法不需要重复登入的举动,举例来说,(1)你以 X window 登入 Linux 后,再以 X 的图形化接口启动终端机,此时那个终端接口并没有需要再次的输入账号与密码,那个 bash 的环 境就称为 non-login shell 了。(2)你在原本的 bash 环境下再次下达 bash 这个指令,同样的也没有输入账号 密码, 那第二个 bash (子程序) 也是 non-login shell 。

login shell 与 non-login shell 读取的配置文件数据并不一样。login shell 会读 /etc/profile 和 [~/.bash_profile | ~/.bash_login | ~/.profile] 这两个文件。 non-login shell 会读取 ~/.bashrc 文件。

由于这些配置文件只有在 shell 登录时才读取,若修改了这些文件如果想立即生效的话就使用 source 命令,这个命令会读入环境配置文件。

还有其他的相关配置文件:

  • /etc/man_db.conf 规范了使用 man 的时候, man page 的路径到哪里去寻找
  • ~/.bash_history 记录了历史命令的文件
  • ~/.bash_logout 注销 bash 后,系统再帮我做完什么动作后才离开,一般默认为空

数据流重导向

数据流重导向 (redirect)是将某个指令执行后应该要出现在屏幕上的数据,传输到其他的地方, 例如文件或者是装置(例如打印机之类)

standard output 与 standard error output

标准输出指的是指令执行所回传的正确的讯息,而标准错误输出为指令执 行失败后,所回传的错误讯息。 数据流重导向可以将 standard output (简称 stdout) 与 standard error output (简称 stderr) 分别传送到其他的文件或装置去,而分别传送所用的特殊字符为:

  • 标准输入(stdin) :代码为 0 ,使用 < 或 <<
  • 标准输出(stdout):代码为 1 ,使用 > 或 >>
  • 标准错误输出(stderr):代码为 2 ,使用 2> 或 2>>

特殊字符的用法:

  • 1> :以覆盖的方法将正确的数据(stdout)输出到指定的文件或装置上
  • 1>>:以累加的方法将正确的数据(stdout)输出到指定的文件或装置上
  • 2> :以覆盖的方法将错误的数据(stderr)输出到指定的文件或装置上
  • 2>>:以累加的方法将错误的数据(stderr)输出到指定的文件或装置上

范例:将 stdout 与 stderr 分存到不同的文件: find /home -name .bashrc > list_right 2> list_error

/dev/null 垃圾桶黑洞装置与特殊写法

/dev/null: 在类Unix系统中,/dev/null,或称空设备,是一个特殊的设备文件,它丢弃一切写入其中的数据(但报告写入操作成功),读取它则会立即得到一个EOF。

如果想将错误的数据丢弃就可以将其重导向至 /dev/null。 例: find /home -name .bashrc 2> /dev/null 如果想将stdout 与 stderr 输出到同一个文件需要用到特殊用法,例: find /home -name .bashrc > list 2>&1

standard input : < 与 <<

< 将原本需要由键盘输入的数据,改由文件内容来取代。 范例: cat > file < ~/.bashrc

管线命令 (pipe)

管线命令 | 仅能处理经由前面一个指令传来的正确信息,即 standard output 的信息,对于 stdandard error 并没有直接处理的能力。在每个管线后面接的第一个数据必定是指令,而且这个指令必须要能够接受 standard input 的 数据。注意:

  • 管线命令仅会处理 standard output,对于 standard error output 会予以忽略
  • 管线命令必须要能够接受来自前一个指令的数据成为 standard input 继续处理才行

撷取命令: cut, grep

撷取讯息通常是针对 一行一行 来分析的,取出我们所想要的。

cut 命令

cut 指令可以将一段讯息的某一段切出来,处理的消息是以行为单位。命令格式:

[dmtsai@study ~]$ cut -d '分隔字符' -f fields <==用于有特定分隔字符 
[dmtsai@study ~]$ cut -c 字符区间            <==用于排列整齐的讯息 
选项与参数: 
-d  :后面接分隔字符。与 -f 一起使用; 
-f  :依据 -d 的分隔字符将一段讯息分区成为数段,用 -f 取出第几段的意思; 
-c  :以字符 (characters) 的单位取出固定字符区间; 

范例:输出 PATH 中的第五个路径:

[admin@centos764 ~]$ echo ${PATH}
/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin:/bin:/sbin:/home/admin/.local/bin:/home/admin/bin
[admin@centos764 ~]$ echo ${PATH} | cut -d ':' -f 5
/bin

grep 命令

grep 分析一行讯息, 若当中有我们所需要的信息,就将该行拿出来。

[dmtsai@study ~]$ grep [-acinv] [--color=auto] '搜寻字符串' filename 
选项与参数: 
-a :将 binary 文件以 text 文件的方式搜寻数据 
-c :计算找到 '搜寻字符串' 的次数 
-i :忽略大小写的不同,所以大小写视为相同 
-n :顺便输出行号 
-v :反向选择,亦即显示出没有 '搜寻字符串' 内容的那一行! 
--color=auto :可以将找到的关键词部分加上颜色的显示喔! 

排序命令: sort, wc, uniq

soct 命令

排序的字符与语系的编码有关,因此, 排序时建议使用 LANG=C 来让语系统一,数据排序比较好一些。 sort 命令格式:

[dmtsai@study ~]$ sort [-fbMnrtuk] [file or stdin] 
选项与参数: 
-f  :忽略大小写的差异,例如 A 与 a 视为编码相同; 
-b  :忽略最前面的空格符部分; 
-M  :以月份的名字来排序,例如 JAN, DEC 等等的排序方法; 
-n  :使用『纯数字』进行排序(默认是以文字型态来排序的); 
-r  :反向排序; 
-u  :就是 uniq ,相同的数据中,仅出现一行代表; 
-t  :分隔符,预设是用 [tab] 键来分隔; 
-k  :以那个区间 (field) 来进行排序的意思 

范例:cat /etc/passwd | sort -t ':' -k 3

uniq 命令

排序完成了,想要将重复的资料仅列出一个显示。命令格式:

[dmtsai@study ~]$ uniq [-ic] 
选项与参数: 
-i  :忽略大小写字符的不同; 
-c  :进行计数 

范例:

[admin@centos764 ~]$ last | cut -d ' ' -f 1 | sort -b | uniq

admin
reboot
root
wtmp

wc 命令

列出文件里面有字数、行数、字符数,命令格式:

[dmtsai@study ~]$ wc [-lwm] 
选项与参数: 
-l  :仅列出行; 
-w  :仅列出多少字(英文单字); 
-m  :多少字符; 

双向重导向: tee

tee 会同时将数据流分送到文件去与屏幕 (screen);而输出到屏幕的,就是 stdout ,那就可以让下个指令继续处理。命令格式:

[dmtsai@study ~]$ tee [-a] file 
选项与参数: 
-a  :以累加 (append) 的方式,将数据加入 file 当中! 

范例: ls -l /home | tee ~/homefile | more




发表评论

评论列表,共 0 条评论

    暂无评论