鸟哥私房菜学习笔记
作者: dkvirus 发表于: 2018-07-20 22:44:34 最近更新: 2018-08-31 16:18:44

一、变量有关命令

1. 查询变量

环境变量可以传递给子进程用,自定义变量只能在当前变量中用。

1.1 变量查询命令

env 查看环境变量
export 查看环境变量
declare 查看所有变量,包括环境变量和自定义变量
set 查看所有变量,包括环境变量和自定义变量

此外,export 和 declare 还有其它用法:

1.2 export 其它用法

将自定义变量转换为环境变量,$ export name 将自定义变量 name 导出为环境变量。

使用 export 查看环境变量就可以看到很多类似 declare -x SHELL="/bin/bash" 的写法,原来是使用 declare 变成的环境变量。

1.3 declare 其它用法

declare 命令有一些参数,可以进行类型转换,也可以将环境变量转换为自定义变量。

  • -i 将后面的变量定义为整数类型;
  • -a 将后面的变量定义为数组类型;
  • -x 将后面的变量定义为环境变量;
  • +x 将后面的变量变成自定义变量;
  • -r 将后面的变量设置为 readonly 只读类型,不可修改,也不可 unset。
  • -p 单独列出变量的类型
1
2
3
4
5
6
$ sum=1+2
$ echo $sum
1+2
$ declare -i sum=1+2
$ echo $sum
3

1.4 set 其它用法

设置终端机一些值,如按键快捷键或其它功能。

$ echo $- 查看所有 set 设置的值。
$ set -u 设置之后在打印未定义的变量就会报错~~

2. 操作变量

2.1 设置变量

1
2
$ name=dkvirus
$ name=$(uname -r)
  • 注意等号两边不能有空格;
  • 自定义变量命名用小写字母,环境变量命名用大写字母;
  • $() 里面可以运行指令,将指令的结果作为变量值;

上面设置变量值为字符串类型,还可以赋值数组,bash 中数组下标从 1 开始。

1
2
3
$ arr[1]="hello"
$ arr[2]="world"
$ echo "${arr[1]}, ${arr[2]}"

2.2 获取变量值

打印变量的值

1
2
3
4
$ echo $name
$ echo ${name}
$ echo 'His name is $name'
$ eccho "His name is $name"

单引号会将字符串原封不动打印出来,双引号可以将 $name 翻译成变量对应的值。

2.3 取消定义的变量

取消设置的变量 $ unset name

2.4 变量内容删除

1
2
3
4
5
6
7
[dkvirus@14:59:57 #73]$ path=$PATH
[dkvirus@15:00:02 #74]$ echo $path
/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/home/dkvirus/.local/bin:/home/dkvirus/bin
[dkvirus@15:00:06 #75]$ echo ${path#/*local/bin:}
/usr/bin:/usr/local/sbin:/usr/sbin:/home/dkvirus/.local/bin:/home/dkvirus/bin
[dkvirus@15:00:42 #76]$ echo ${path##/*local/bin:}
/home/dkvirus/bin

echo ${path#/*local/bin:} 其中 # 表示从左往右操作,/*local/bin: 是过滤规则。只删除符合规则最短那一个,使用 ## 删除符合规则最长那一个。

echo ${path%/*local/bin:} 其中 % 表示从右往左操作,/*local/bin: 是过滤规则。只删除符合规则最短那一个,使用 %% 删除符合规则最长那一个。

2.5 变量内容替换

将 path 变量内第一个 sbin 字符串替换成 SBIN,$ echo ${path/sbin/SBIN}
将 path 变量内所有 sbin 字符串替换成 SBIN,变量后使用双斜线,$ echo ${path//sbin/SBIN}

2.6 变量为空默认值

1
2
3
4
5
[dkvirus@15:04:11 #77]$ echo $name

[dkvirus@15:09:35 #78]$ name=${name-dkvirus}
[dkvirus@15:09:45 #79]$ echo $name
dkvirus

使用 - 号设置变量为空时的默认值。

3. 用户输入变量的值 read

read 命令,指定变量的值由用户输入。如下示例,-p 参数后面跟的字符串是提示文字,最后的 result 是命令名,回车之后等待用户输入,用户输入的值就是变量的值。

1
2
3
4
$ read -p "请输入 yes/no: " result
no
$ echo $result
no

4. 命令提示符变量 $PS1

有意思的东西:设置命令提示符,环境变量 PS1,相关值列举如下:

符号 意义
\d 显示【星期 月 日】的日期格式,如:”Mon Feb 2”
\H 完整主机名,如:aaa.bbb.ccc
\h 或去主机名第一部分内容,如:aaa
\t 显示 24 小时制时间格式,如:20:10:11
\T 显示 12 小时制时间格式
\A 显示 24 小时制时间格式,值有小时和分钟
\@ 显示 12 小时制 am 或 pm
\u 目前使用用户
\v bash 版本信息
\w 完整工作目录
\W 工作目录最后一个目录名
\# 下达的第几个命令
\$ 提示符,root 用户为 #,其它用户为 $

$$ 当前 shell 的进程号 pid
$? 返回上一个命令执行响应码,为 0 表示上一个命令执行成功,非 0 表示上一个命令执行失败。

二、远程登录 bash 几个配置文件

1. login shell 与 non-login shell

通过 xshell 远程登录阿里云主机,需要输入账号密码这种方式叫做 login shell。

我的机器安装了 centos7 图形化系统,登录系统后点击终端程序打开 shell,此时不需要输入账号密码,这种称为 non-login shell。

二者在启动 shell 程序会访问不同的配置文件。

2. login-shell 相关配置文件

配置文件有全局和个人之分。顾名思义,全局设置的配置文件对所有用户生效,用户也可以修改自己的配置文件实现个性化功能。

shell 初始化会先执行 /etc/profile,在执行 ~/.bash_profile

2.1 全局配置文件

入口文件 /etc/profile,懂点英文和 shell script 就能看懂写的啥。这只是个入口文件,细节的内容在其它几个配置文件中描述:

  • /etc/bashrc 在这个文件写函数和别名;
  • /etc/profile.d/ 不要直接改 /etc/profile,有什么想法在这个目录下新增 sh 文件实现功能;
  • /usr/share/bash-completion/completions/ tab 补齐功能具体实现与这个目录有关。

2.2 个人配置文件

入口文件 ~/.bash_profile,同样是入口文件,内容在其它配置文件中描述:~/.bashrc 写别名或函数在这里整。

用户尽量不要修改全局配置文件,有啥想法在个人配置文件里使劲整。

2.3 non-login shell 相关配置文件

shell 会读取 ~/.bashrc 文件,这个文件内部会自动读取 /etc/bashrc 文件的内容。

2.4 其它配置文件

  • /etc/man_db.conf 敲 man 命令时去那里找 man page 文档;
  • ~/.bash_history 历史命令存放文件;
  • ~/.bash_logout 退出 shell 时系统帮忙做哪些事,一般用来删除临时目录中的文件。

三、数据流重定向与管道

1. 标准输入输出

standard input:执行一个命令,可能需要参数,这个参数就是标准输入,代码是0,使用 < 或 <<;
standard output:执行一个命令,执行成功会将正确信息打印到屏幕上,这个正确信息就是标准输出,代码是1,使用 > 或 >>;
standard error output:执行一个命令,执行失败将错误信息打印到屏幕上,这个错误信息就是标准错误输出,代码是2,使用 2> 或 2>>。

示例:cat /etc/passwd 原本应当打印 passwd 文件的内容,但是现在 bash 中确不见任何信息,这是因为将内容重定向到用户目录下的 passwd.bak 文件中去了。一个 > 表示覆盖新文件里的内容,两个 >> 表示将内容追加到新文件中。

1
$ cat /etc/passwd > ~/passwd.bak

将标准输出和标准错误输出分开存放文件。这一点十分常见,如 nginx 这种程序就是分别记录登录成功与登录失败日志的,分别存放于 /var/log/nginx/access.log/var/log/nginx/error.log 的。实际操作使用 > 重定向到成功文件,使用 2> 重定向到错误文件中。

1
$ find /home -name .bashrc > access.log 2> error.log

知道可能会打印错误信息,将错误信息忽略掉不显示,需要用到 /dev/null “黑洞设备”。

1
$ find /home -name .bashrc 2> /dev/null

将正确信息和错误信息写入到同一个文件中。

1
2
3
$ find /home -name .bashrc > access.log 2>&1

$ find /home -name .bashrc &> access.log

2. 一次执行多个命令

使用分号 ; 隔开,一次可以执行多个命令,等前一个命令执行完才能执行后一个,如:

1
$ sync; sync; sync

使用 &&,前一个命令执行成功才能执行后一个命令,命令执行成功通过 $? 等于 0 判断,如:

1
$ ls /tmp/abc && touch /tmp/abc/hehe

使用 ||,前一个命令执行成功就结束,前一个命令执行失败了才开始执行后一个命令,如:

1
$ ls /tmp/abc || mkdir /tmp/abc

&& 与 || 配合使用,/tmp/abc 目录存在则创建 hehe 文件,目录不存在,先创建目录再创建文件,如:

1
$ ls /tmp/abc || mkdir /tmp/abc && touch /tmp/abc/hehe

3. 管道命令

管道感觉和数据重定向差不多,就是将管道命令 | 前面的 standard output 作为 standard input 传给后面的命令。

4. 管道常用工具命令

4.1 cut 截取行数据

选项 说明
-d 以什么进行分隔行
-f 选取第几段
-c 取第几个字符

示例1:-d 以冒号对 $PATH 进行分隔,-f 选取第几段。

1
2
3
4
5
6
[dkvirus@hd1h2g ~]$ echo $PATH
/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/home/dkvirus/.local/bin:/home/dkvirus/bin
[dkvirus@hd1h2g ~]$ echo $PATH | cut -d ':' -f 5
/home/dkvirus/.local/bin
[dkvirus@hd1h2g ~]$ echo $PATH | cut -d ':' -f 3,5
/usr/local/sbin:/home/dkvirus/.local/bin

示例2:-c 8- 取每一行第 8 个以后的字符,-c 8-20 取 8-20 个字符,-c 8+ 取前 8 个字符。

1
$ history 5 | cut -c 8-

4.2 grep 过滤行

分析每一行,有符合过滤条件的,就将这一行显示。-v 表示相反,将不符合过滤条件的行显示出来。

1
2
$ last | grep root
$ last | grep -v root

4.3 sort 排序命令

选项 说明
-f 忽略大小写
-b 忽略最前面空格
-M 以月份排序
-n 以数字排序
-r 反向排序
-u 去重
-t 分隔符
-k -t 分隔符分成几段,-k 选取哪一段进行排序
1
$ last | cut -d ' ' -f 1 | sort -u

有个问题,就是 cut -d ‘ ‘ 貌似只是以一个空格作为分隔符,想要的是就是以空格作为分隔符…

4.4 uniq 去重+计数命令

1
2
3
4
5
$ last | cut -d ' ' -f 1 | sort | uniq -c
101 dkvirus
3 reboot
82 root
1 wtmp

uniq -c 既去重,又计算了每个重复项的个数。

上面打印的信息有一点比较奇怪,我明明在阿里云主机上没有建 reboot 和 wtmp 用户,为什么会有呢??还有登录信息,更奇怪的是在 /etc/passwd 这个文件里又找不到这两个用户。。难道这就是传说中的后门,还是阿里云整的骚操作???

4.5 wc 统计个数

wc 可以统计一个文件里有多少行,多少字,多少字符。

选项 说明
-l 仅统计多少行
-w 仅统计多少字,一个英文单词算一个字
-m 多少字符,一个英文字母、一个空格、一个换行都算一个字符
1
2
3
hello world

hehe

输出含义为:3行3个字,18个字符。3行很容易看到,3个字表示有三个英文单词,18行=14个英文字符 + 3个换行 + 1个空格(hello world 之间的空格)。

1
2
$ cat test | wc
3 3 18

4.6 tee 双向重定向

将 last 的标准输出存入 list 文件,既然将 last 的标准输出继续往后面的管道传。

1
$ last | tee list | cut -d ' ' -f 1

4.7 tr

示例1:将一段信息内小写字符变成大写字符

1
$ last | tr [a-z] [A-Z]

五、其它

ulimit 文件限制命令

应用场景:Linux 是多用户系统,同时登入是个用户,每个用户同时打开 100 个文件,每个文件大小约 100M,Linux 主机内存一下子就要用 10G 才够。ulimit 可以限制每个用户使用内存、cpu 的量。

ulimit -a 查看当前登录用户 dkvirus 的相关限制,0 表示没有限制,看到 open files 那一行数值是 65535,表示 dkvirus 这个用户同时只能打开 65535 个文件。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
[dkvirus@14:53:44 #67]$ ulimit -a
core file size (blocks, -c) 0
data seg size (kbytes, -d) unlimited
scheduling priority (-e) 0
file size (blocks, -f) unlimited
pending signals (-i) 7283
max locked memory (kbytes, -l) 64
max memory size (kbytes, -m) unlimited
open files (-n) 65535
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

设置用户仅能建立 10M 大小的文件。(10M = 1024Kb * 10 = 10240Kb)

1
2
3
4
[dkvirus@14:53:52 #68]$ ulimit -f 10240
[dkvirus@14:56:17 #69]$ ulimit -a | grep 'file size'
core file size (blocks, -c) 0
file size (blocks, -f) 10240

跟语系有关的命令

查询系统支持所有语系 $ locale -a,查询 /usr/lib/locale/ 目录下的文件,该目录下文件是个二进制文件,无法直接查看内容。

如果要修改语系,整体系统默认语系文件为 /etc/locale.conf,该文件存储 LANG 变量的值。

设置别名

1
2
$ alias cls=clear
$ alias h=history

等号左右两边不能有空格。

邮箱在哪个目录下

/var/spool/mail/dkvirus

命令执行顺序

1
2
3
[dkvirus@15:34:13 #88]$ which ll
alias ll='ls -l --color=auto'
/usr/bin/ls

可以看到同一个命令 ll 在系统中可能有多个对应的文件,那系统怎么知道该用哪个文件执行命令呢?这有个顺序,如下:

  • 文件的相对路径/绝对路径;
  • alias 别名设置的命令;
  • bash 内建命令;
  • $PATH 变量指定的路径;

source

用户远程登录,shell 初始化的时候会执行一次 /etc/profile 和 ~/.bash_profile 文件,之后如果用户修改了这两个文件里的内容,是不会立刻生效的,要等到下次登录 shell 时才会执行生效。如果想要立刻生效怎么办??source /etc/profile 会立刻执行该文件,也可以将 source 换成小数点 .,写成 . /etc/profile。

stty —— 键盘设置

stty —— set tty

图形化界面安装的 Linux 会提供 6 个终端界面,那玩意就是 tty,tty1 ~ tty6.

用 xshell 远程连接 linux 主机获取 shell 环境,那玩意也叫 tty??

总之,stty 可以设置 bash 里按键啦。

查看所有按键及其内容

1
$ stty -a

上面按键含义如下,^ 表示 Ctrl。

  • intr。终止,interrupt,发一个终端信息给正在运行的程序;
  • quit。停止??跟终止有区别??
  • erase。删除键
  • kill。删除目前指令列上所有文字
  • eof。结束输入
  • start。某个程序需停止后,重新启动
  • stop。停止目前屏幕的输出

其它与终端机有关环境配置文件:

  • /etc/inputrc 按键设定功能
  • /etc/DIR_COLORS
  • /usr/share/terminfo/

鸟哥不建议用户自己修改终端环境,只要了解怎么整的即可。

终端组合键

组合键 说明
Ctrl + c 终止当前命令
Ctrl + d 结束输入
Ctrl + m 回车,相当于按 Enter
Ctrl + s 暂停屏幕输出
Ctrl + q 恢复屏幕输出
Ctrl + u 提示符下,删除整行命令
Ctrl + z 将命令放到后台运行

六、查看

1. 查看系统可用的 shell

1
# cat /etc/shells

2. 查看敲过的命令

1
2
$ history
$ history 3 # 列举最近敲过的 3 个命令

最多保存 1000 条,这个限制由环境变量 HISTSIZE 控制。

这些输出保存在 ~/.bash_history 中,正常情况下,只有每次注销系统时才会将本次登录 shell 使用的命令保存到 ~/.bash_history 中。

3. 查询指令是否为 bash 内建命令

type 命令可以判断命名是否为 bash 内建命令,也可以用来判断命令是否存在,后者跟 which 功能有点类似。

1
2
[dkvirus@hd1h2g ~]$ type -t cd
builtin

加上 -t 参数,会打印三个值:

  • file。外部指令,如:nginx;
  • alias。命令别名,如:ll;
  • buildin。bash 内建命令。
1
2
3
4
[dkvirus@hd1h2g ~]$ type cd
cd is a shell builtin
[dkvirus@hd1h2g ~]$ type nginx
nginx is /usr/sbin/nginx

不输入参数,外部命令打印完整路径。

1
2
[dkvirus@hd1h2g ~]$ type javac
-bash: type: javac: not found

输入的命令不存在,会打印 not found,说明软件还没安装。

查询操作系统版本

uname -r

查询 bash 进站与欢迎信息

1
2
3
4
[dkvirus@15:36:05 #90]$ cat /etc/issue
\S (terminal: \l)
Date: \d \t
Kernel \r on an \m

上面有一些奇怪的符号,具体含义如下:

符号 含义
\d 本地端日期
\t 本地端时间
\l 显示第几个终端机接口
\m 显示硬件等级(i386/i686)
\n 显示主机网络名称
\O 显示域名
\r 操作系统版本($ uname -r)
\S 操作系统名称
\v 操作系统版本

貌似使用 xshell 登录阿里云主机看到这玩意,自己电脑装了 linux,切换到终端界面才能看到欢迎界面。

书上介绍 $ cat /etc/issue.net 可以查询远程登录时欢迎界面,然而测试并不是…….

cat /etc/motd 每个用户登录时都会看到的信息,这个命令比较有用,比如管理员修改这个文件可以告知普通用户什么时候会进行系统维护。

首页
友链
归档
dkvirus
动态
RSS