Bash进阶

bash登陆环境

用户每次使用 Shell,都会开启一个与 Shell 的 Session(对话)。

Session 有两种类型:登录 Session 和非登录 Session,也可以叫做 login shell 和 non-login shell。

这里针对的是linux,在mac上不太一样,mac上都没有/etc/profile.d这个文件夹

$ cat /etc/profile 
# System-wide .profile for sh(1)

if [ -x /usr/libexec/path_helper ]; then
	eval `/usr/libexec/path_helper -s`
fi

if [ "${BASH-no}" != "no" ]; then
	[ -r /etc/bashrc ] && . /etc/bashrc
fi

登录 Session

登录 Session 是用户登录系统以后,系统为用户开启的原始 Session,通常需要用户输入用户名和密码进行登录。

登录 Session 一般进行整个系统环境的初始化,启动的初始化脚本依次如下。

  • /etc/profile:所有用户的全局配置脚本。
  • /etc/profile.d目录里面所有.sh文件
  • ~/.bash_profile:用户的个人配置脚本。如果该脚本存在,则执行完就不再往下执行。
  • ~/.bash_login:如果~/.bash_profile没找到,则尝试执行这个脚本(C shell 的初始化脚本)。如果该脚本存在,则执行完就不再往下执行。
  • ~/.profile:如果~/.bash_profile~/.bash_login都没找到,则尝试读取这个脚本(Bourne shell 和 Korn shell 的初始化脚本)。

Linux 发行版更新的时候,会更新/etc里面的文件,比如/etc/profile,因此不要直接修改这个文件。如果想修改所有用户的登陆环境,就在/etc/profile.d目录里面新建.sh脚本。

如果想修改你个人的登录环境,一般是写在~/.bash_profile里面。下面是一个典型的.bash_profile文件。

# .bash_profile
PATH=/sbin:/usr/sbin:/bin:/usr/bin:/usr/local/bin
PATH=$PATH:$HOME/bin
SHELL=/bin/bash
MANPATH=/usr/man:/usr/X11/man
EDITOR=/usr/bin/vi
PS1='\h:\w\$ '
PS2='> '
if [ -f ~/.bashrc ]; then
. ~/.bashrc
fi
export PATH
export EDITOR

可以看到,这个脚本定义了一些最基本的环境变量,然后执行了~/.bashrc

bash命令的--login参数,会强制执行登录 Session 会执行的脚本。

$ bash --login

bash命令的--noprofile参数,会跳过上面这些 Profile 脚本。

$ bash --noprofile

非登录 Session

非登录 Session 是用户进入系统以后,手动新建的 Session,这时不会进行环境初始化。比如,在命令行执行bash命令,就会新建一个非登录 Session。

非登录 Session 的初始化脚本依次如下。

  • /etc/bash.bashrc:对全体用户有效。
  • ~/.bashrc:仅对当前用户有效。

对用户来说,~/.bashrc通常是最重要的脚本。非登录 Session 默认会执行它,而登陆 Session 一般也会通过调用执行它。由于每次执行 Bash 脚本,都会新建一个非登录 Session,所以~/.bashrc也是每次执行脚本都会执行的。

bash命令的--norc参数,可以禁止在非登录 Session 执行~/.bashrc脚本。

$ bash --norc

bash命令的--rcfile参数,指定另一个脚本代替.bashrc

$ bash --rcfile testrc

.bash_logout

~/.bash_logout脚本在每次退出 Session 时执行,通常用来做一些清理工作和记录工作,比如删除临时文件,记录用户在本次 Session 花费的时间。

如果没有退出时要执行的命令,这个文件也可以不存在。

启动选项

为了方便 Debug,有时在启动 Bash 的时候,可以加上启动参数。

  • -n:不运行脚本,只检查是否有语法错误。
  • -v:输出每一行语句运行结果前,会先输出该行语句。
  • -x:每一个命令处理完以后,先输出该命令,再进行下一个命令的处理。

键盘绑定

Bash 允许用户定义自己的快捷键。全局的键盘绑定文件默认为/etc/inputrc,你可以在主目录创建自己的键盘绑定文件.inputrc文件。

命令提示符

用户进入 Bash 以后,Bash 会显示一个命令提示符,用来提示用户在该位置后面输入命令。

环境变量 PS1

命令提示符通常是美元符号$,对于根用户则是井号#。这个符号是环境变量PS1决定的,执行下面的命令,可以看到当前命令提示符的定义。

bash-3.2$ echo $PS1
\s-\v\$

Bash 允许用户自定义命令提示符,只要改写这个变量即可。改写后的PS1,可以放在用户的 Bash 配置文件.bashrc里面,以后新建 Bash 对话时,新的提示符就会生效。要在当前窗口看到修改后的提示符,可以执行下面的命令。

$ source ~/.bashrc

命令提示符的定义,可以包含特殊的转义字符,表示特定内容。

  • \a:响铃,计算机发出一记声音。
  • \d:以星期、月、日格式表示当前日期,例如“Mon May 26”。
  • \h:本机的主机名。
  • \H:完整的主机名。
  • \j:运行在当前 Shell 会话的工作数。
  • \l:当前终端设备名。
  • \n:一个换行符。
  • \r:一个回车符。
  • \s:Shell 的名称。
  • \t:24小时制的hours:minutes:seconds格式表示当前时间。
  • \T:12小时制的当前时间。
  • \@:12小时制的AM/PM格式表示当前时间。
  • \A:24小时制的hours:minutes表示当前时间。
  • \u:当前用户名。
  • \v:Shell 的版本号。
  • \V:Shell 的版本号和发布号。
  • \w:当前的工作路径。
  • \W:当前目录名。
  • \!:当前命令在命令历史中的编号。
  • \#:当前 shell 会话中的命令数。
  • \$:普通用户显示为$字符,根用户显示为#字符。
  • \[:非打印字符序列的开始标志。
  • \]:非打印字符序列的结束标志。

举例来说,[\u@\h \W]\$这个提示符定义,显示出来就是[user@host ~]$(具体的显示内容取决于你的系统)。

[user@host ~]$ echo $PS1
[\u@\h \W]\$

颜色

默认情况下,命令提示符是显示终端预定义的颜色。Bash 允许自定义提示符颜色。

使用下面的代码,可以设定其后文本的颜色。

  • \033[0;30m:黑色
  • \033[1;30m:深灰色
  • \033[0;31m:红色
  • \033[1;31m:浅红色
  • \033[0;32m:绿色
  • \033[1;32m:浅绿色
  • \033[0;33m:棕色
  • \033[1;33m:黄色
  • \033[0;34m:蓝色
  • \033[1;34m:浅蓝色
  • \033[0;35m:粉红
  • \033[1;35m:浅粉色
  • \033[0;36m:青色
  • \033[1;36m:浅青色
  • \033[0;37m:浅灰色
  • \033[1;37m:白色

举例来说,如果要将提示符设为红色,可以将PS1设成下面的代码。

PS1='\[\033[0;31m\]<\u@\h \W>\$'

但是,上面这样设置以后,用户在提示符后面输入的文本也是红色的。为了解决这个问题, 可以在结尾添加另一个特殊代码\[\033[00m\],表示将其后的文本恢复到默认颜色。

PS1='\[\033[0;31m\]<\u@\h \W>\$\[\033[00m\]'

除了设置前景颜色,Bash 还允许设置背景颜色。

  • \033[0;40m:蓝色
  • \033[1;44m:黑色
  • \033[0;41m:红色
  • \033[1;45m:粉红
  • \033[0;42m:绿色
  • \033[1;46m:青色
  • \033[0;43m:棕色
  • \033[1;47m:浅灰色

下面是一个带有红色背景的提示符。

PS1='\[\033[0;41m\]<\u@\h \W>\$\[\033[0m\] '

PS2,PS3,PS4

除了PS1,Bash 还提供了提示符相关的另外三个环境变量。

环境变量PS2是命令行折行输入时系统的提示符,默认为>

 liushun@ls  ~  echo "e      
dquote> 
dquote> d            
dquote> 
dquote> "

环境变量PS3是使用select命令时,系统输入菜单的提示符:#?

 liushun@liushun  ~/Documents/GoWorkspace/src/MyLearn/sh  ./geth.sh                                                 
Which environment do you want to start your geth on?
1) bsc-prod-primary  3) eth-prod-primary  5) bsc-dev
2) bsc-prod-backup   4) eth-prod-backup   6) eth-dev
#? 7
Invalid environment.

环境变量PS4默认为+。它是使用 Bash 的-x参数执行脚本时,每一行命令在执行前都会先打印出来,并且在行首出现的那个提示符。

归档和备份

gzip

gzip 程序用来压缩文件,原文件的压缩版(添加gz后缀名)会替代原文件。gunzip 程序用来还原压缩版本。

$ gzip test.txt
$ gunzip test.txt.gz

gzip的参数如下。

  • -c 把输出写入到标准输出,并且保留原始文件。也有可能用 -stdout 和 -to-stdout 选项来指定。
  • -d 解压缩。正如 gunzip 命令一样。也可以用 -decompress 或者 -uncompress 选项来指定.
  • -f 强制压缩,即使原始文件的压缩文件已经存在了,也要执行。也可以用 -force 选项来指定。
  • -h 显示用法信息。也可用 -help 选项来指定。
  • -l 列出每个被压缩文件的压缩数据。也可用 -list 选项。
  • -r 若命令的一个或多个参数是目录,则递归地压缩目录中的文件。也可用 -recursive 选项来指定。
  • -t 测试压缩文件的完整性。也可用 -test 选项来指定。
  • -v 显示压缩过程中的信息。也可用 -verbose 选项来指定。
  • -number 设置压缩指数。number 是一个在1(最快,最小压缩)到9(最慢,最大压缩)之间的整数。 数值1和9也可以各自用 -fast 和 -best 选项来表示。默认值是整数6。
# 查看解压缩后的内容
gunzip -c test.txt.gz | less

bzip2

bzip2程序与gzip程序相似,但是使用了不同的压缩算法,舍弃了压缩速度,实现了更高的压缩级别。在大多数情况下,它的工作模式等同于gzip。 由bzip2压缩的文件,用扩展名.bz2表示。

$ bzip2 foo.txt
$ bunzip2 foo.txt.bz2

gzip程序的所有选项(除了-r),bzip2 程序同样也支持。同样有 bunzip2 和 bzcat 程序来解压缩文件。bzip2 文件也带有 bzip2recover 程序,其会 试图恢复受损的 .bz2 文件。

zip

zip程序既是压缩工具,也是一个打包工具,读取和写入.zip文件。

$ zip options zipfile file...

它的用法如下。

# 将指定目录压缩成zip文件
$ zip -r playground.zip playground

ziptar命令有一个相反之处。如果压缩文件已存在,其将被更新而不是被替代。这意味着会保留此文件包,但是会添加新文件,同时替换匹配的文件。

解压使用unzip命令。

$ unzip ../playground.zip

unzip命令的参数如下。

  • -l 列出文件包中的内容而不解压
  • -v 显示冗余信息
  • -p 输出发送到标准输出
$ unzip -p ls-etc.zip | less

tar

tar是tape archive的简称,原来是一款制作磁带备份的工具,现在主要用于打包。一个 tar 包可以由一组独立的文件,一个或者多个目录,或者两者混合体组成。

tar程序的语法如下。

$ tar mode[options] pathname...

tar支持以下模式。

  • c 表示create,为文件和/或目录列表创建归档文件。
  • x 抽取归档文件。
  • r 追加具体的路径到归档文件的末尾。
  • t 列出归档文件的内容。

支持的参数如下。

  • f 表示file,用来指定生成的文件。

模式和参数可以写在一起,而且不需要开头的短横线。注意,必须首先指定模式,然后才是其它的选项。

# 创建子目录的tar包
$ tar cf playground.tar playground
# 查看tar包内容
$ tar tf playground.tar
# 查看更详细的列表信息
$ tar tvf playground.tar
# 还原归档文件
$ tar xf playground.tar
# 还原单个文件
$ tar xf archive.tar pathname
# 还原文件到指定目录
$ tar xvf archive.tar -C /home/me/
# 追加文件
$ tar rf archive.tar file.txt
# 验证归档文件内容是否正确
$ tar tvfW archive.tar
# 支持通配符
$ tar xf ../playground2.tar --wildcards 'home/me/playground/\*.txt'

注意,tar命令还原的时候,总是还原为相对路径。如果归档的时候,保存的是绝对路径,那么还原的时候,这个绝对路径会整个变成相对路径。

find命令可以与tar命令配合使用。

$ find playground -name 'file.txt' -exec tar rf playground.tar '{}' '+'

上面的命令先用find程序找到所有名为file.txt的文件,然后使用追加模式(r)的tar命令,把匹配的文件添加到归档文件playground.tar里面。

这种tarfind的配合使用,可以创建逐渐增加的目录树或者整个系统的备份。通过find命令匹配新于某个时间戳的文件,我们就能够创建一个归档文件,其只包含新于上一个 tar 包的文件。

tar支持压缩功能。

# 打成gzip压缩包
$ tar czvf assets.tar.gz dist
# 打成bz2压缩包
$ tar cvfj assets.tar.bz2 dist
# 解压 tar.gz 文件
$ tar xzv archive.tar.gz
$ tar xvf archive.tar.gz
# 解压bz2压缩包
$ tar xvf archive.tar.bz2
# 显示gzip压缩包内容
$ tar tvf archive.tar.gz
# 显示bz2压缩包内容
$ tar tvf archive.tar.bz2
# 从gzip压缩包取出单个文件
$ tar zxvf archive.tar.gz file.txt
# 从bz2压缩包取出单个文件
$ tar jxvf archive.tar.bz2 file.txt
# 按通配符取出文件
$ tar zxvf archive.tar.gz --wildcards '*.php'
$ tar jxvf archive.tar.bz2 --wildcards '*.php'
# 追加文件到压缩包
$ tar rvf archive.tar.gz xyz.txt
$ tar rvf archive.tar.bz2 xyz.txt

异步任务

Bash脚本有时候需要同时执行多个任务。通常这涉及到启动一个脚本,依次,启动一个或多个子脚本来执行额外的任务,而父脚本继续运行。然而,当一系列脚本 以这种方式运行时,要保持父子脚本之间协调工作,会有一些问题。也就是说,若父脚本或子脚本依赖于另一方,并且 一个脚本必须等待另一个脚本结束任务之后,才能完成它自己的任务,这应该怎么办?

bash 有一个内置命令,能帮助管理诸如此类的异步执行的任务。wait 命令导致一个父脚本暂停运行,直到一个 特定的进程(例如,子脚本)运行结束。

首先我们将演示一下 wait 命令的用法。为此,我们需要两个脚本,一个父脚本:

#!/bin/bash
# async-parent : Asynchronous execution demo (parent)
echo "Parent: starting..."
echo "Parent: launching child script..."
source ./sync_c.sh &
pid=$!
echo "Parent: child (PID= $pid) launched."
echo "Parent: continuing..."
sleep 2
echo "Parent: pausing to wait for child to finish..."
wait $pid
echo "Parent: child is finished. Continuing..."
echo "Parent: parent is done. Exiting."

和一个子脚本:

#!/bin/bash
# async-child : Asynchronous execution demo (child)
echo "Child: child is running..."
sleep 5
echo "Child: child is done. Exiting."

在这个例子中,我们看到该子脚本是非常简单的。真正的操作通过父脚本完成。在父脚本中,子脚本被启动, 并被放置到后台运行。子脚本的进程 ID 记录在 pid 变量中,这个变量的值是 $! shell 参数的值,它总是 包含放到后台执行的最后一个任务的进程 ID 号。

父脚本继续,然后执行一个以子进程 PID 为参数的 wait 命令。这就导致父脚本暂停运行,直到子脚本退出, 意味着父脚本结束。

当执行后,父子脚本产生如下输出:

Parent: starting...
Parent: launching child script...
Parent: child (PID= 48310) launched.
Parent: continuing...
Child: child is running...
Parent: pausing to wait for child to finish...
Child: child is done. Exiting.
Parent: child is finished. Continuing...
Parent: parent is done. Exiting.

文件操作

CP

cp命令用于将文件(或目录)拷贝到目的地。

# 拷贝单个文件
$ cp source dest
# 拷贝多个文件
$ cp source1 source2 source3 dest
# -i 目的地有同名文件时会提示确认
$ cp -i file1 file2
# -r 递归拷贝,将dir1拷贝到dir2,完成后dir2生成一个子目录dir1
# dir2如果不存在,将被创建
# 拷贝目录时,该参数是必需的
$ cp -r dir1 dir2
# -u --update 只拷贝目的地没有的文件,或者比目的地同名文件更新的文件
$ cp -u *.html destination

其他参数

  • -a 拷贝时保留所有属性,包括所有者与权限
  • -v 显示拷贝的详细信息

mv

mv命令用于将源文件移动到目的地。

# 移动单个文件
$ mv item1 item2
# 移动多个文件
$ mv file1 file2 dir1
# 将dir1拷贝进入dir2,完成后dir2将多出一个子目录dir1
# 如果dir2不存在,将会被创建
$ mv dir1 dir2

参数

  • -i 覆盖已经存在的文件时,会提示确认
  • -u 只移动目的地不存在的文件,或比目的地更新的文件

rm

rm命令用于删除文件。

参数。

  • -i 文件存在时,会提示确认。
  • -r 递归删除一个子目录
  • -f 如果删除不存在的文件,不报错
  • -v 删除时展示详细信息

ln

ln命令用于建立链接文件。

# 新建硬链接
$ ln file link
# 新建软链接
$ ln -s item link
参数:
	-i 交互模式。
	-s 软链接(符号链接)。如果不加 “-s” 选项,则建立硬链接文件
	-d 允许超级用户制作目录的硬链接。
	-b 删除,覆盖以前建立的链接
	-f 强制。如果目标文件已经存在,则删除目标文件后再建立链接文件

(1)软链接 软链接是Linux中常用的命令,它的功能是某一文件在另外一个位置建立一个同步的链接,相当于C语言中的指针,建立的链接直接指向源文件所在的地址,软链接不会另外占用资源,当同一文件需要在多个位置被用到的时候,就会使用到软连接。

(2)硬链接 硬链接在是另外一个位置创建源文件的链接文件,相当于复制了一份,占用资源会倍增。硬链接一旦创建,源文件和链接文件任何一方修改文件都会同步修改。

screenshot2024-10-20 10.09.57

文件系统

ls

ls目录可以显示指定目录的内容。不加参数时,显示当前目录的内容。ls命令也可以显示指定文件是否存在。

$ ls foo.txt
foo.txt

-l参数可以显示文件的详细信息。

$ ls -l test.txt                                                       
-rw-r--r--  1 liushun  staff  13  9  6 13:27 test.txt

上面命令输出结果的第一栏,是文件的类型和权限。

文件类型分为以下几种。

  • - 普通文件
  • d 目录
  • l 符号链接。注意,对于符号链接文件,剩余的文件属性总是”rwxrwxrwx”。
  • c 字符设备文件,指按照字节流处理数据的设备,比如调制解调器。
  • b 块设备文件,指按照数据块处理数据的设备,比如硬盘。

其他参数的用法。

# 显示多个目录的内容
$ ls ~ /usr
# -a --all 显示隐藏文件
$ ls -a
# -A 与-a类似,但是不显示当前目录和上一级目录两个点文件
$ ls -A
# -l 显示详细信息
$ ls -l
# -1 单列显示,每行只显示一个文件,只展示一个名字
$ ls -1
# -d 显示当前目录本身,而不是它的内容
# 通常与-l配合使用,列出一个目录本身的详细信息
$ ls -dl # drwx------+ 16 liushun  staff  512 10 20 10:14 .
# -F 目录名之后添加斜杠,可执行文件后面添加星号
$ ls -F
# -h 与-l配合使用,将文件大小显示为人类可读的格式
# -t 按文件修改时间排序,修改晚的排在前面
$ ls -t
# -s 按文件大小排序,
# --reverse 显示结果倒序排列
$ ls -lt --reverse

stat

stat命令是加强版的ls命令,可以显示一个文件的详细信息。

tat test.txt             
16777231 18289095 -rw-r--r-- 1 liushun staff 0 13 "Oct 20 10:14:52 2024" "Sep  6 13:27:02 2024" "Oct 20 10:14:51 2024" "Sep  6 13:27:02 2024" 4096 8 0 test.txt

touch

touch用来设置或更新文件的访问,更改,和修改时间。然而,如果一个文件名参数是一个不存在的文件,则会创建一个空文件。

如果该文件已经存在,就会把它的修改时间设置为当前时间。

file

file命令显示指定文件的类型。

$ file test.txt 
test.txt: ASCII text

chmod

chmod命令用于更改文件的权限,是“change mode”的缩写。

$ chmod 600 foo.txt

chmod还可以接受四个缩写,为不同的对象单独设置权限。

  • u 所有者“user”的简写
  • g 用户组“group”的缩写
  • o 其他所有人“others”的简写
  • a 所有人“all”的简写
# 为所有者添加可执行权限
$ chmod u+x foo.txt
# 删除所有者的可执行权限
$ chmod u-x foo.txt
# 为所有人添加可执行权限,等价于 a+x
$ chmod +x foo.txt
# 删除其他人的读权限和写权限。
$ chmod o-rw foo.txt
# 设定用户组和其他人的权限是读权限和写权限
$ chmod go=rw foo.txt
# 为所有者添加执行权限,设定用户组和其他人为读权限和写权限,多种设定用逗号分隔
$ chmod u+x,go=rw foo.txt

添加权限。

  • +x 添加执行权限
  • +r 设置读权限
  • +w 设置写权限
  • +rwx 设置所有读、写和执行权限。

删除权限只需将+更改为-,就可以删除任何已设置的指定权限。可以使用-R(或--recursive)选项来递归地操作目录和文件。

设置精确权限,可以使用=代替+-来实现此操作。如果想为用户、组或其他用户设置不同的权限,可以使用逗号将不同表达式分开(例如ug=rwx,o=rx)。

由于一共有3种可能的权限。也可以使用八进制数代替符号来设置权限。通过这种方式设置的权限最多使用3个八进制数。第1个数定义用户权限,第2个数定义组权限,第3个数定义其他权限。这3个数中的每一个都通过添加想要的权限设置来构造:读 (4)、写 (2) 和执行 (1)。

比如600,就表示用户具有读写权限,组和其他没有权限。

umask

umask用来查看和设置权限掩码。

$ umask
022

命令显示当前系统之中,默认的文件掩码是022,转为二进制就是000 010 010。9位分别代表文件三种使用对象的三类权限。只要对应位置上是1,就表示关闭该项权限,所以010就表示关闭读权限。

新建文件时,通常不会带有执行权限,也就是说,新建文件的默认权限是rw-rw-rw-。如果文件掩码是0022,那么用户组和其他人的写权限也会被拿掉。

$ ls -l test.txt 
-rw-r--r--  1 liushun  staff  13 10 20 10:24 test.txt

umask后面跟着参数,就表示设置权限掩码。

$ umask 0000

上面命令将权限掩码设为0000,实际上就是关闭了权限掩码。

umask命令设置的掩码值只能在当前Shell会话中生效,若当前Shell会话结束后,则必须重新设置。

du

du命令用于查看指定目录的大小。

$ du -hs /path/to/directory

显示第一层子目录的大小。

$ du -h -d 1
 45M	./WechatWorkspace
 64K	./docker
2.0G	./VscodeWorkspace
495M	./IdeaWorkspace
1.3G	./Programs
256M	./PycharmWorkspace
597M	./master
6.5G	./GoWorkspace
7.5M	./internalship
 11G	.

参数的含义。

  • -h 表示人类可读的格式
  • -s 表示总结信息,否则会显示该目录内所有文件和子目录的信息。

find

搜索一个给定目录(以及它的子目录),来查找文件。

usage: find [-H | -L | -P] [-EXdsx] [-f path] path ... [expression]
       find [-H | -L | -P] [-EXdsx] -f path [path ...] [expression]
# 输出当前目录的所有子目录和文件(含子目录)
$ find .
# 显示当前目录的文件总数
$ find . | wc -l # 440484
# 当前目录的子目录总数
$ find . -type d | wc -l # 69113
# 当前目录的文件总数(不含子目录)
$ find . -type f | wc -l # 371222
# 当前目录的文件名匹配“*.JPG”且大于1M的文件总数
$ find . -type f -name "\*.JPG" -size +1M | wc -l

-type参数支持的文件类型。

  • b 块设备文件
  • c 字符设备文件
  • d 目录
  • f 普通文件
  • l 符号链接

-size参数支持的文件大小类型。

  • b 512 个字节块。如果没有指定单位,则这是默认值。
  • c 字节
  • w 两个字节的字
  • k 千字节
  • M 兆字节
  • G 千兆字节

这个很强大,超多参数可以参考,还可以正则匹配。

硬件操作

df

df命令查看硬盘信息。

$ df -h
Filesystem        Size    Used   Avail Capacity iused ifree %iused  Mounted on
/dev/disk3s1s1   228Gi    13Gi    86Gi    14%    394k  902M    0%   /
devfs            201Ki   201Ki     0Bi   100%     696     0  100%   /dev
/dev/disk3s6     228Gi   1.0Gi    86Gi     2%       1  902M    0%   /System/Volumes/VM
/dev/disk3s2     228Gi    11Gi    86Gi    12%    1.1k  902M    0%   /System/Volumes/Preboot
/dev/disk3s4     228Gi   633Mi    86Gi     1%     267  902M    0%   /System/Volumes/Update
/dev/disk1s2     500Mi   6.0Mi   482Mi     2%       1  4.9M    0%   /System/Volumes/xarts
/dev/disk1s1     500Mi   6.1Mi   482Mi     2%      29  4.9M    0%   /System/Volumes/iSCPreboot
/dev/disk1s3     500Mi   1.1Mi   482Mi     1%     102  4.9M    0%   /System/Volumes/Hardware
/dev/disk3s5     228Gi   115Gi    86Gi    58%    2.0M  902M    0%   /System/Volumes/Data
map auto_home      0Bi     0Bi     0Bi   100%       0     0     -   /System/Volumes/Data/home
/dev/disk3s1     228Gi    13Gi    86Gi    14%    404k  902M    0%   /System/Volumes/Update/mnt1

free

free命令查看内存占用情况。mac的zsh上没这个指令,linux上才有

[root@ip-172-31-23-171 ~]# free
               total        used        free      shared  buff/cache   available
Mem:        15985008     9510064      149716        8852     6325228     6129812
Swap:              0           0           0

mount

mount不带参数时,显示当前挂载的文件系统。

➜  ~ mount
/dev/disk3s1s1 on / (apfs, sealed, local, read-only, journaled)
devfs on /dev (devfs, local, nobrowse)
/dev/disk3s6 on /System/Volumes/VM (apfs, local, noexec, journaled, noatime, nobrowse)
/dev/disk3s2 on /System/Volumes/Preboot (apfs, local, journaled, nobrowse)
/dev/disk3s4 on /System/Volumes/Update (apfs, local, journaled, nobrowse)
/dev/disk1s2 on /System/Volumes/xarts (apfs, local, noexec, journaled, noatime, nobrowse)
/dev/disk1s1 on /System/Volumes/iSCPreboot (apfs, local, journaled, nobrowse)
/dev/disk1s3 on /System/Volumes/Hardware (apfs, local, journaled, nobrowse)
/dev/disk3s5 on /System/Volumes/Data (apfs, local, journaled, nobrowse, protect)
map auto_home on /System/Volumes/Data/home (autofs, automounted, nobrowse)
/dev/disk3s1 on /System/Volumes/Update/mnt1 (apfs, sealed, local, journaled, nobrowse)

mount带参数时,用于将设备文件挂载到挂载点,-t参数用来指定文件系统类型。

umount

umount命令用来卸载设备。

$ umount [设备名]
$ umount /dev/hdc

命名管道

在大多数类似 Unix 的操作系统中,有可能创建一种特殊类型的文件,叫做命名管道。命名管道用来在 两个进程之间建立连接,也可以像其它类型的文件一样使用。

命令管道的行为类似于文件,但实际上形成了先入先出(FIFO)的缓冲。和普通(未命令的)管道一样, 数据从一端进入,然后从另一端出现。通过命令管道,有可能像这样设置一些东西:

process1 > named_pipe

process2 < named_pipe

表现出来就像这样:

process1 | process2

设置一个命名管道

使用 mkfifo 命令能够创建命令管道:

$ mkfifo pipe1
$ ls -l pipe1  
prw-r--r--  1 liushun  staff  0 10 20 12:50 pipe1

这里我们使用 mkfifo 创建了一个名为 pipe1 的命名管道。使用 ls 命令,我们查看这个文件, 看到位于属性字段的第一个字母是 “p”,表明它是一个命名管道。

使用命名管道

为了演示命名管道是如何工作的,将需要两个终端窗口(或用两个虚拟控制台代替)。 在第一个终端中,输入一个简单命令,并把命令的输出重定向到命名管道:

$ ls -l > pipe1

按下 Enter 按键之后,命令将会挂起。这是因为在管道的另一端没有任何接受数据。当这种现象发生的时候, 据说是管道阻塞了。一旦绑定一个进程到管道的另一端,该进程开始从管道中读取输入的时候,这种情况会消失。 使用第二个终端窗口,输入这个命令。

$ cat < pipe1 
total 8
drwx------@   4 liushun  staff   128  9 23 21:37 Applications
drwx------@   7 liushun  staff   224 10 17 10:42 Desktop
drwx------+  16 liushun  staff   512 10 20 10:14 Documents
drwx------@  16 liushun  staff   512 10 17 13:31 Downloads
drwx------@ 104 liushun  staff  3328  9 24 20:19 Library
drwx------    5 liushun  staff   160  4 10  2024 Movies
drwx------+   6 liushun  staff   192  3 10  2024 Music
drwx------+   5 liushun  staff   160  3 10  2024 Pictures
drwxr-xr-x@   3 liushun  staff    96  4 15  2024 Postman
drwxr-xr-x+   5 liushun  staff   160  3 10  2024 Public
drwxr-xr-x    4 liushun  staff   128  9 24 20:20 ScreenPal
drwx------    3 liushun  staff    96  8 10 17:28 default.etcd
-rw-r--r--    1 liushun  staff   100  9  1 16:15 dump.rdb
drwxr-xr-x    3 liushun  staff    96  9  6 17:36 go
drwxr-xr-x    4 liushun  staff   128  7 16 17:10 logs
drwxr-xr-x    4 liushun  staff   128  7 16 17:10 nacos
prw-r--r--    1 liushun  staff     0 10 20 12:48 pipe1

然后产自第一个终端窗口的目录列表出现在第二个终端中,并作为来自 cat 命令的输出。在第一个终端 窗口中的 ls 命令一旦它不再阻塞,会成功地结束。

进程管理

ps

ps命令用来列出进程信息。

$ ps
	PID TTY           TIME CMD
72215 ttys000    0:01.76 -zsh
45118 ttys001    0:07.12 -zsh
12351 ttys002    0:03.31 /bin/zsh --login -i
12411 ttys003    0:10.01 /bin/zsh --login -i
46581 ttys005    0:00.60 /bin/zsh --login -i

不带任何参数时,ps只列出与当前Session相关的进程。输出结果中,PID是进程ID、TTY是进程的终端号(如果显示?,则表示进程没有终端),TIME是消耗的CPU时间,CMD是触发进程的命令。

x参数列出所有进程的详细信息,包括不在当前Session的信息。

ps x   
  PID   TT  STAT      TIME COMMAND
  575   ??  S      9:56.72 /usr/sbin/distnoted agent
  576   ??  S      4:40.03 /usr/sbin/cfprefsd agent
...

输出结果,会多出STAT一栏,表示状态。它的各种值如下。

  • R 正在运行或准备运行
  • S 正在睡眠,即没有运行,正在等待一个事件唤醒
  • D 不可中断睡眠。进程正在等待 I/O,比如磁盘驱动器的I/O
  • T 已停止,即进程停止运行
  • Z “僵尸”进程。即这是一个已经终止的子进程,但父进程还没有清空它(没有把子进程从进程表中删除)
  • < 高优先级进程。这可能会授予一个进程更多重要的资源,给它更多的 CPU 时间。
  • N 低优先级进程。一个低优先级进程(一个“好”进程)只有当其它高优先级进程执行之后,才会得到处理器时间。

aux参数可以显示更多信息。

$ ps aux 
USER               PID  %CPU %MEM      VSZ    RSS   TT  STAT STARTED      TIME COMMAND
_windowserver      368  23.2  0.7 415379072 120864   ??  Ss    71024  1841:00.04 /System/Library/PrivateFrameworks/SkyLig
liushun          34285   9.2  0.2 410272800  40416   ??  S    三09上午 207:24.90 /Applications/Xmind.app/Contents/Framewo

输出结果包含的列的含义如下。

  • USER 用户ID,表示进程的所有者
  • %CPU 百分比表示的 CPU 使用率
  • %MEM 百分比表示的内存使用率
  • VSZ 虚拟内存大小
  • RSS 进程占用的物理内存的大小,以千字节为单位。
  • START 进程运行的起始时间。若超过24小时,则用天表示。

top

top命令可以查看机器的当前状态。

$ top
top - 05:11:56 up 79 days, 20:18,  2 users,  load average: 0.11, 0.07, 0.09
Tasks: 198 total,   1 running, 197 sleeping,   0 stopped,   0 zombie
%Cpu(s):  0.7 us,  0.0 sy,  0.0 ni, 98.6 id,  0.5 wa,  0.0 hi,  0.2 si,  0.0 st
MiB Mem :  15610.4 total,    154.7 free,   9308.2 used,   6147.5 buff/cache
MiB Swap:      0.0 total,      0.0 free,      0.0 used.   5965.4 avail Mem 

    PID USER      PR  NI    VIRT    RES    SHR S  %CPU  %MEM     TIME+ COMMAND                           
3320879 root      20   0   12.7g   8.8g  20232 S  11.3  57.4 376:02.79 geth-linux                         
3387071 root      20   0  224036   3648   2860 R   0.3   0.0   0:00.02 top         

它的输出结果分为两部分,最上面是系统概要,下面是进程列表,以 CPU 的使用率排序。

jobs

jobs命令用来查看后台任务。

$ jobs
[1]+ Running            xlogo &

输出结果之中,每个后台任务会有一个编号。上面结果中,xlogo的编号是1+表示正在运行。

fg

fg命令用于将后台任务切换到前台。

$ fg %1

fg命令之后,跟随着一个百分号和工作序号,用来指定切换哪一个后台任务。如果只有一个后台任务,那么fg命令可以不带参数。

bg

bg命令用于将一个暂停的前台任务,转移到后台。只有暂停的任务,才能使用bg命令,因为正在运行的任务,命令行是无法输入的。

$ bg %1

Ctrl + z可以暂停正在运行的前台任务。

kill

kill命令用于杀死进程。它的参数是进程ID。

kill命令的实质是操作系统向进程发送信号。在使用 Ctrl-c 的情况下,会发送一个叫做 INT(中断)的信号;当使用 Ctrl-z 时,则发送一个叫做 TSTP(终端停止)的信号。

$ kill [-signal] PID

下面是常见信号。

  • HUP:编号1,表示挂起。发送这个信号到前台程序,程序会终止。许多守护进程也使用这个信号,来重新初始化。这意味着,当发送这个信号到一个守护进程后, 这个进程会重新启动,并且重新读取它的配置文件。Apache 网络服务器守护进程就是一个例子。
  • INT:编号2,中断。实现和Ctrl-c一样的功能,由终端发送。通常,它会终止一个程序。
  • KILL:编号9,杀死。进程可能选择忽略这个信号。所以,操作系统不发送该信号到目标进程,而是内核立即终止这个进程。当一个进程以这种方式终止的时候,它没有机会去做些“清理”工作,或者是保存劳动成果。因为这个原因,把 KILL 信号看作杀手锏,当其它终止信号失败后,再使用它。
  • TERM:编号15,终止。这是 kill 命令发送的默认信号。如果程序仍然“活着”,可以接受信号,那么这个信号终止。
  • CONT:编号18,继续。在停止一段时间后,进程恢复运行。
  • STOP:编号19,停止。这个信号导致进程停止运行,而没有终止。像 KILL 信号,它不被 发送到目标进程,因此它不能被忽略。
  • QUIT:编号3,退出
  • SEGV:编号11,段错误。如果一个程序非法使用内存,就会发送这个信号。也就是说,程序试图写入内存,而这个内存空间是不允许此程序写入的。
  • TSTP:编号20,终端停止。当按下 Ctrl-z 组合键后,终端发送这个信号。不像 STOP 信号, TSTP 信号由目标进程接收,且可能被忽略。
  • WINCH:编号28,改变窗口大小。当改变窗口大小时,系统会发送这个信号。 一些程序,像 top 和 less 程序会响应这个信号,按照新窗口的尺寸,刷新显示的内容。

-l参数可以列出所有信号。

$ kill -l
HUP INT QUIT ILL TRAP ABRT EMT FPE KILL BUS SEGV SYS PIPE ALRM TERM URG STOP TSTP CONT CHLD TTIN TTOU IO XCPU XFSZ VTALRM PROF WINCH INFO USR1 USR2

pstree

[root@ip-172-31-23-171 ~]# pstree
systemd─┬─2*[agetty]
        ├─amazon-ssm-agen───10*[{amazon-ssm-agen}]
        ├─atd
        ├─auditd───{auditd}
        ├─chronyd
        ├─dbus-broker-lau───dbus-broker
        ├─geth-linux───29*[{geth-linux}]
        ├─gssproxy───5*[{gssproxy}]
        ├─irqbalance───{irqbalance}
        ├─lsmd
        ├─nginx───8*[nginx]
        ├─rngd───4*[{rngd}]
        ├─sshd─┬─sshd───sshd───bash
        │      └─sshd───sshd───bash───pstree
        ├─systemd───(sd-pam)
        ├─systemd-homed
        ├─systemd-inhibit───acpid
        ├─systemd-journal
        ├─systemd-logind
        ├─systemd-network
        ├─systemd-resolve
        ├─systemd-udevd
        └─systemd-userdbd───3*[systemd-userwor]

重定向

输入输出

命令说明
command > file将输出重定向到 file。
command < file将输入重定向到 file。
command >> file将输出以追加的方式重定向到 file。
n > file将文件描述符为 n 的文件重定向到 file。
n >> file将文件描述符为 n 的文件以追加的方式重定向到 file。
n >& m将输出文件 m 和 n 合并。
n <& m将输入文件 m 和 n 合并。
<< tag将开始标记 tag 和结束标记 tag 之间的内容作为输入。

一般情况下,每个 Unix/Linux 命令运行时都会打开三个文件:

  • 标准输入文件(stdin):stdin的文件描述符为0,Unix程序默认从stdin读取数据。
  • 标准输出文件(stdout):stdout 的文件描述符为1,Unix程序默认向stdout输出数据。
  • 标准错误文件(stderr):stderr的文件描述符为2,Unix程序会向stderr流中写入错误信息。

>

>用来将标准输出重定向到指定文件。

$ ls -l /usr/bin > ls-output.txt

如果重定向后的指定文件已经存在,就会被覆盖,不会有任何提示。

如果命令没有任何输出,那么重定向之后,得到的是一个长度为0的文件。因此,>具有创建新文件或改写现存文件、将其改为长度0的作用。

 复制代码$ > ls-output.txt

>>

>>用来将标准输出重定向追加到指定文件。

$ ls -l /usr/bin >> ls-output.txt

2>

2>用来将标准错误重定向到指定文件。

$ ls -l /bin/usr 2> ls-error.txt

标准输出和标准错误,可以重定向到同一个文件。

$ ls -l /bin/usr > ls-output.txt 2>&1 # 将2合并到1,然后输出到1
# 或者
$ ls -l /bin/usr &> ls-output.txt
# 追加到同一个文件
$ ls -l /bin/usr &>> ls-output.txt

如果不希望输出错误信息,可以将它重定向到一个特殊文件/dev/null

$ ls -l /bin/usr 2> /dev/null

|

|用于将一个命令的标准输出,重定向到另一个命令的标准输入。

$ ls -l /usr/bin | less

不要将>|混淆。

$ ls > less

上面命令会在当前目录,生成一个名为less的文本文件。

tee

tee命令用于同时将标准输出重定向到文件,以及另一个命令的标准输入。

$ ls /usr/bin | tee ls.txt | grep zip

命令替换

命令替换(command substitution)指的是将一个命令的输出,替换进入另一个命令。$(command)表示命令替换,另一种写法是使用反引号。

$ echo $(ls)# 或者
$ echo `ls`
echo `ls`          
Applications Desktop Documents Downloads Library Movies Music Pictures Postman Public ScreenPal default.etcd dump.rdb go logs nacos pipe1
$ ls -l $(which cp)# 或者
$ ls -l `which cp`

basename

basename命令清除 一个路径名的开头部分,只留下一个文件的基本名称。

$ basename docker/compose/Docker
Docker

系统信息

uname

uname命令返回当前机器的信息。

# 内核的版本
$ uname -r
23.2.0
# CPU 架构
$ uname -m 
arm64
$ uname -a 
Darwin ls.local 23.2.0 Darwin Kernel Version 23.2.0: Wed Nov 15 21:59:33 PST 2023; root:xnu-10002.61.3~2/RELEASE_ARM64_T8112 arm64

service

service命令可以查看当前正在运行的服务。mac上没有

$ service --status-all
 [ + ]  apache2
 [ ? ]  atd
 [ - ]  bootlogd

上面代码中,+表示正在运行,-表示已经停止,?表示service命令不了解相关信息。

文本处理

cat

cat可以文件的内容,显示在标准输出。

$ cat test.txt 
hello world!
abd
dahk
wqowie

它也可以同时输出多个文件内容。

$ cat text1 text2

如果调用cat命令时没有任何参数,它将读取标准输入,然后显示到标准输出。按下Ctrl + d,将会结束cat读取标准输入。利用这一点,可以将键盘输入写入指定文件,按下Ctrl + d结束输入。

$ cat > lazy_dog.txt

它的参数如下。

  • -n 输出结果显示行号
  • -s 将多个连续的空白行,输出为一行
  • -A 输出结果中显示控制符,比如Tab键显示为^I,行尾显示$

nl

nl命令为文本文件添加行号,显示在标准输出。

$ nl test.txt 
     1	hello world!
     2	abd
     3	dahk
     4	wqowie

sort

sort命令将文本文件的所有行排序后输出。

$ sort test.txt  
abd
dahk
hello world!
wqowie
  • -b --ignore-leading-blanks 默认情况下,排序用的是每行的第一个字符。这个参数忽略每行开头的空格,从第一个非空白字符开始排序。
  • -f --ignore-case 让排序不区分大小写。
  • -n --numeric-sort 按照数值排序,而不是字符值,用于行首是数值的情况。
  • -r --reverse 按相反顺序排序。结果按照降序排列,而不是升序。
  • -o --output=file 把排好序的输出结果发送到文件,而不是标准输出。
  • -u 输出结果中删除重复行

wc

wc命令输出一个文本文件的统计信息(word count),一共有三个值,分别为行数、词数和字节数。

$ wc test.txt 
       4       5      29 test.txt

如果使用-l参数,则只输出行数。

wc -l test.txt 
       4 test.txt

head

head命令返回文本文件的头部,默认显示10行。

-n参数指定显示的行数。

$ head -n 5 ls-output.txt

tail

tail命令返回文本文件的尾部,默认显示10行。

-n参数指定显示的行数。

$ tail -n 5 ls-output.txt

-f会实时追加显示新增的内容,常用于实时监控日志,按Ctrl + c停止。

$ tail -100f /var/log/messages

grep

grep程序用于在指定文件之中,搜索符合某个模式的行,并把搜索结果输出到标准输出。

$ grep keyword foo.txt

grep程序可以同时搜索多个文件。

$ grep keyword f*.txt

-l参数输出匹配的文件名,而不是文件行。

$ grep -l bzip dirlist*.txt

如果想搜索文件名,而不是文件内容,可以使用重定向。

$ ls /usr/bin | grep zip

上面命令会输出/usr/bin目录中,文件名中包含子字符串zip的所有文件。

参数的含义。

  • -c--count 输出匹配的数量,而不是匹配的文本行。如果使用了-v,则输出不匹配的数量。
  • -h--no-filename 应用于多文件搜索,不在每行匹配的文本前,输出文件名
  • -i--ignore-case 忽略大小写
  • -l--files-with-matches 输出包含匹配项的文件名,而不是文本行本身
  • -L--files-without-match 类似于-l,但输出不包含匹配项的文件名
  • -n--line-number 每个匹配行之前输出其对应的行号
  • -v--invert-match 只返回不符合模式的行

时间管理

date 命令

date命令用于输出当前时间

$ date       
2024年10月20日 星期日 16时30分52秒 CST

date命令后面用加号(+)指定显示的格式。

$ date +%d_%b_%Y
20_10_2024
$ date +%D      
10/20/24
$ date +%F-%T
2024-10-20-16:31:31

完整的格式参数如下。

  • %a 星期名的缩写(Sun)
  • %A 星期名的全称(Sunday)
  • %b 月份的缩写(Jan)
  • %B 月份的全称(January)
  • %c 日期和时间(Thu Mar 3 23:05:25 2005)
  • %C 世纪,就是年份数省略后两位(20)
  • %d 一个月的第几天(01)
  • %D 日期,等同于%m/%d/%y
  • %e 一个月的第几天,用空格补零,等同于%_d
  • %F 完整的日期,等同于%Y-%m-%d
  • %g last two digits of year of ISO week number (see %G)
  • %G year of ISO week number (see %V); normally useful only with %V
  • %h 等同于%b
  • %H 小时(00..23)
  • %I 小时(01..12)
  • %j day of year (001..366)
  • %k hour ( 0..23)
  • %l hour ( 1..12)
  • %m month (01..12)
  • %M minute (00..59)
  • %N nanoseconds (000000000..999999999)
  • %p locale’s equivalent of either AM or PM; blank if not known
  • %P like %p, but lower case
  • %r locale’s 12-hour clock time (e.g., 11:11:04 PM)
  • %R 24-hour hour and minute; same as %H:%M
  • %s seconds since 1970-01-01 00:00:00 UTC
  • %S second (00..60)
  • %T time; same as %H:%M:%S
  • %u day of week (1..7); 1 is Monday
  • %U week number of year, with Sunday as first day of week (00..53)
  • %V ISO week number, with Monday as first day of week (01..53)
  • %w day of week (0..6); 0 is Sunday
  • %W week number of year, with Monday as first day of week (00..53)
  • %x locale’s date representation (e.g., 12/31/99)
  • %X locale’s time representation (e.g., 23:13:48)
  • %y last two digits of year (00..99)
  • %Y year
  • %z +hhmm numeric timezone (e.g., -0400)
  • %😒 +hh:mm numeric timezone (e.g., -04:00)
  • %:😒 +hh:mm:ss numeric time zone (e.g., -04:00:00)
  • %Z alphabetic time zone abbreviation (e.g., EDT)

cal 命令

cal命令用于显示日历。不带有参数时,显示的是当前月份。

$ cal         
      十月 2024         
日 一 二 三 四 五 六  
       1  2  3  4  5  
 6  7  8  9 10 11 12  
13 14 15 16 17 18 19  
20 21 22 23 24 25 26  
27 28 29 30 31 
$ cal 9 2024
      九月 2024         
日 一 二 三 四 五 六  
 1  2  3  4  5  6  7  
 8  9 10 11 12 13 14  
15 16 17 18 19 20 21  
22 23 24 25 26 27 28  
29 30  

用户管理

Linux系统是一个多用户多任务的分时操作系统,任何一个要使用系统资源的用户,都必须首先向系统管理员申请一个账号,然后以这个账号的身份进入系统。

用户的账号一方面可以帮助系统管理员对使用系统的用户进行跟踪,并控制他们对系统资源的访问;另一方面也可以帮助用户组织文件,并为用户提供安全性保护。

每个用户账号都拥有一个唯一的用户名和各自的口令。用户在登录时键入正确的用户名和口令后,就能够进入系统和自己的主目录。

实现用户账号的管理,要完成的工作主要有如下几个方面:

  • 用户账号的添加、删除与修改。
  • 用户口令的管理。
  • 用户组的管理。

每个用户都有一个用户组,系统可以对一个用户组中的所有用户进行集中管理。不同Linux 系统对用户组的规定有所不同,如Linux下的用户属于与它同名的用户组,这个用户组在创建用户时同时创建。用户组的管理涉及用户组的添加、删除和修改。组的增加、删除和修改实际上就是对/etc/group文件的更新。

id

id命令用于查看指定用户的用户名和组名。

$ id
uid=501(liushun) gid=20(staff) groups=20(staff),12(everyone),61(localaccounts),79(_appserverusr),80(admin),81(_appserveradm),98(_lpadmin),701(com.apple.sharepoint.group.1),33(_appstore),100(_lpoperator),204(_developer),250(_analyticsusers),395(com.apple.access_ftp),398(com.apple.access_screensharing),399(com.apple.access_ssh),400(com.apple.access_remote_ae)

id输出结果分为三个部分,分别是UID(用户编号和用户名)、GID(组编号和组名),groups(用户所在的所有组)。

用户帐户的信息,存放在/etc/passwd文件里面;用户组的信息,存放在/etc/group文件里面。

# 返回UID
$ id -u [UserName]
501
# 返回GID
$ id -g [UserName]
20
# 返回用户名
$ id -un [UserName]
liushun
# 返回组名
$ id -gn [UserName]
staff

上面的命令,如果省略用户名,则返回当前用户的信息。

su

su命令允许以另一个用户的身份,启动一个新的 shell 会话,或者是以这个用户的身份来发布一个命令。

$ su otherUser

执行上面的命令以后,系统会提示输入密码。通过以后,就以另一个用户身份在执行命令了。

如果不加用户名,则表示切换到root用户。

$ su

-l参数表示启动一个需要登录的新的Shell,这意味着工作目录会切换到该用户的主目录。它的缩写形式是-

$ su -

上面命令表示,切换到root用户的身份,且工作目录也切换到root用户的主目录。

-c参数表示只以其他用户的身份,执行单个命令,而不是启动一个新的Session。

$ su -c 'command' # 实例
$ su -c 'ls -l /root/*'

sudo

sudo命令很类似su命令,但有几点差别。

  • 对于管理员来说,sudo命令的可配置性更高
  • sudo命令通常只用于执行单个命令,而不是开启另一个Session。
  • sudo命令不要求超级用户的密码,而是用户使自己的密码来认证。

sudo的设置在文件/etc/sudoers之中。

-l参数列出用户拥有的所有权限。

$ sudo -l                      
Password:
Matching Defaults entries for liushun on ls:
    env_reset, env_keep+=BLOCKSIZE, env_keep+="COLORFGBG COLORTERM", env_keep+=__CF_USER_TEXT_ENCODING,
    env_keep+="CHARSET LANG LANGUAGE LC_ALL LC_COLLATE LC_CTYPE", env_keep+="LC_MESSAGES LC_MONETARY LC_NUMERIC LC_TIME",
    env_keep+="LINES COLUMNS", env_keep+=LSCOLORS, env_keep+=SSH_AUTH_SOCK, env_keep+=TZ, env_keep+="DISPLAY
    XAUTHORIZATION XAUTHORITY", env_keep+="EDITOR VISUAL", env_keep+="HOME MAIL", lecture_file=/etc/sudo_lecture

User liushun may run the following commands on ls:
    (ALL) ALL

chown

chown命令用来更改文件或目录的所有者和用户组。使用这个命令需要超级用户权限。

$ chown [owner][:[group]] file

下面是一些例子。

# 更改文件所有者
$ sudo chown bob foo.txt
# 更改文件所有者和用户组
$ sudo chown bob:users foo.txt
# 更改用户组
$ sudo chown :admins foo.txt
# 更改文件所有者和用户组(用户 bob 登录系统时,所属的用户组)
$ sudo chown bob: foo.txt

chgrp

chgrp命令更改用户组,用法与chown命令类似。

useradd

useradd命令用来新增用户。

$ useradd -G admin -d /home/bill -s /bin/bash -m bill

上面命令新增用户bill,参数-G指定用户所在的组,参数d指定用户的主目录,参数s指定用户的 Shell,参数m表示如果该目录不存在,则创建该目录。

usermod

usermod命令用来修改用户的各项属性。

$ usermod -g sales jerry

上面的命令修改用户jerry属于的主要用户组为sales

$ usermod -G sales jerry

上面的命令修改用户jerry属于的次要用户组为sales

adduser

adduser命令用来将一个用户加入用户组。

$ sudo adduser username grouptoadd

groupadd

groupadd命令用来新建一个用户组。

$ sudo groupadd group1
$ sudo adduser foobar group1

groupdel

groupdel命令用来删除一个用户组。

$ sudo groupdel group1

passwd

passwd命令用于修改密码。

# 修改自己的密码
$ passwd
# 修改其他用户的密码
$ sudo passwd [user]

shell命令

命令的类别

Bash可以使用的命令分成四类。

  • 可执行程序
  • Shell 提供的命令
  • Shell 函数
  • 前三类命令的别名

type, whatis

type命令可以显示命令类型。

$ type command

下面是几个例子。

$ type ls   
ls is an alias for ls -G
$ type cp
cp is /bin/cp

whatis命令显示指定命令的描述。

$ whatis ls
.....

alias, unalias

alias命令用来为命令起别名。

$ alias foo='cd /usr; ls; cd -'
$ type foo
foo is aliased to `cd /usr; ls ; cd -'

注意,默认情况下,别名只在当前Session有效。当前Session结束时,这些别名就会消失。

alias命令不加参数时,显示所有有效的别名。

unalias命令用来取消别名。

which

which命令显示可执行程序的路径。

$ which ls
/bin/ls

which命令用于Shell内置命令时(比如cd),将没有任何输出。

help,man

help命令用于查看Shell内置命令的帮助信息,man命令用于查看可执行命令的帮助信息。

$ help cd
$ man ls

man里面的文档一共有8类,如果同一个命令,匹配多个文档,man命令总是返回第一个匹配。如果想看指定类型的文档,命令可以采用下面的形式。

$ man 5 passwd

export

export命令用于将当前进程的变量,输出到所有子进程。

Last Updated:
Contributors: liushun-ing