传统上,Linux shell 是 Bash (Bourne again Shell)。本章提及“shell”时,指的是 Bash。还有其他 shell 可用(ash、csh、ksh、zsh 等),每个都有不同的特性和功能。如果您需要有关其他 shell 的更多信息,请在 YaST 中搜索shell。
shell 可以被以下列方式调用:
交互式登录 shell。 在登录到机器时使用,通过 --login 选项调用 Bash,或者通过 SSH 登录到远程机器时使用。
“普通”交互式 shell。 通常是在启动 xterm、konsole、gnome-terminal 或类似命令行界面 (CLI) 工具时的情况。
非交互式 shell。 在命令行中调用 shell 脚本时被调用。
每个 shell 读取不同的配置文件。下表显示了登录和非登录 shell 配置文件。
Bash 根据其运行的 shell 类型以特定顺序查找其配置文件。有关更多详细信息,请参阅 Bash 手册页 (man 1 bash)。搜索标题 INVOCATION。
|
文件 |
描述 |
|---|---|
|
|
请勿修改此文件,否则您的修改可能会在下次更新时被销毁。 |
|
|
如果您扩展了 |
|
|
包含特定程序的系统级配置文件 |
|
|
在此处插入登录 shell 的用户特定配置 |
登录 shell 还会引用 表 14.2,“非登录 shell 的 Bash 配置文件”中列出的配置文件。
|
|
请勿修改此文件,否则您的修改可能会在下次更新时被销毁。 |
|
|
使用此文件仅插入您的 Bash 系统级修改 |
|
|
在此处插入用户特定配置 |
此外,Bash 还使用多个文件
|
文件 |
描述 |
|---|---|
|
|
包含您键入的所有命令的列表 |
|
|
退出时执行 |
|
|
用户定义的常用命令别名。有关定义别名的更多详细信息,请参阅 |
有一些特殊的 shell 可以阻止用户登录系统:/bin/false 和 /sbin/nologin。当用户尝试登录系统时,两者都会静默失败。这旨在作为系统用户的安全措施,尽管现代 Linux 操作系统有更有效的工具来控制系统访问,例如 PAM 和 AppArmor。
openSUSE Leap 上的默认设置是将 /bin/bash 分配给人类用户,将 /bin/false 或 /sbin/nologin 分配给系统用户。nobody 用户由于历史原因使用 /bin/bash,因为它是一个具有最低权限的用户,曾经是系统用户的默认设置。然而,当多个系统用户使用 nobody 时,所获得的一点点安全性就会丧失。应该可以将它更改为 /sbin/nologin;最快的测试方法是更改它并查看它是否破坏任何服务或应用程序。
使用以下命令列出 /etc/passwd 中分配给所有用户(系统用户和人类用户)的 shell。输出根据系统上的服务和用户而异。
> sort -t: -k 7 /etc/passwd | awk -F: '{print $1"\t" $7}' | column -t
tux /bin/bash
nobody /bin/bash
root /bin/bash
avahi /bin/false
chrony /bin/false
dhcpd /bin/false
dnsmasq /bin/false
ftpsecure /bin/false
lightdm /bin/false
mysql /bin/false
postfix /bin/false
rtkit /bin/false
sshd /bin/false
tftp /bin/false
unbound /bin/false
bin /sbin/nologin
daemon /sbin/nologin
ftp /sbin/nologin
lp /sbin/nologin
mail /sbin/nologin
man /sbin/nologin
nscd /sbin/nologin
polkitd /sbin/nologin
pulse /sbin/nologin
qemu /sbin/nologin
radvd /sbin/nologin
rpc /sbin/nologin
statd /sbin/nologin
svn /sbin/nologin
systemd-coredump /sbin/nologin
systemd-network /sbin/nologin
systemd-timesync /sbin/nologin
usbmux /sbin/nologin
vnc /sbin/nologin
wwwrun /sbin/nologin
messagebus /usr/bin/false
scard /usr/sbin/nologin下表简要概述了 Linux 系统上最重要的上层目录。在以下列表中查找有关目录和重要子目录的更详细信息。
|
目录 |
内容 |
|---|---|
|
|
根目录——目录树的起点。 |
|
|
基本二进制文件,例如系统管理员和普通用户都需要使用的命令。通常也包含 shell,例如 Bash。 |
|
|
引导加载程序的静态文件。 |
|
|
访问主机特定设备所需的文件。 |
|
|
主机特定的系统配置文件。 |
|
|
保存系统上所有拥有账户的用户的家目录。然而, |
|
|
基本共享库和内核模块。 |
|
|
可移动媒体的挂载点。 |
|
|
临时挂载文件系统的挂载点。 |
|
|
附加应用程序软件包。 |
|
|
超级用户 |
|
|
基本系统二进制文件。 |
|
|
系统提供的服务数据。 |
|
|
临时文件。 |
|
|
只读数据的辅助层级。 |
|
|
可变数据,例如日志文件。 |
|
|
仅当您的系统上同时安装了 Microsoft Windows* 和 Linux 时可用。包含 Windows 数据。 |
以下列表提供了更详细的信息,并给出了一些可在目录中找到的文件和子目录的示例
/bin
包含 root 和其他用户都可以使用的基本 shell 命令。这些命令包括 ls、mkdir、cp、mv、rm 和 rmdir。/bin 还包含 Bash,即 openSUSE Leap 中的默认 shell。
/boot
包含启动所需的数据,例如引导加载程序、内核和在内核开始执行用户模式程序之前使用的其他数据。
/dev
保存表示硬件组件的设备文件。
/etc
包含控制 X Window System 等程序运行的本地配置文件。/etc/init.d 子目录包含可在引导过程中执行的 LSB init 脚本。
/home/USERNAME
保存系统上每个拥有账户的用户的私人数据。此处的文件只能由其所有者或系统管理员修改。默认情况下,您的电子邮件目录和个人桌面配置以隐藏文件和目录的形式位于此处,例如 .gconf/ 和 .config。
如果您在网络环境中工作,您的家目录可能会被映射到文件系统中除 /home 之外的目录。
/lib
包含引导系统和运行根文件系统中命令所需的基本共享库。Windows 中共享库的等效项是 DLL 文件。
/media
包含可移动媒体(例如 CD-ROM、闪存盘和数码相机(如果它们使用 USB))的挂载点。/media 通常保存除系统硬盘之外的任何类型的驱动器。当您的可移动媒体插入或连接到系统并已挂载时,您可以从此处访问它。
/mnt
此目录提供了一个临时挂载文件系统的挂载点。root 可以在此处挂载文件系统。
/opt
保留用于安装第三方软件。可选软件和大型附加程序包可以在此处找到。
/root
用户 root 的家目录。root 的个人数据位于此处。
/run
一个由 systemd 和各种组件使用的 tmpfs 目录。/var/run 是 /run 的符号链接。
/sbin
正如 s 所表示的,此目录包含超级用户的实用程序。/sbin 除了 /bin 中的二进制文件外,还包含引导、恢复和修复系统所必需的二进制文件。
/srv
保存系统提供的服务数据,例如 FTP 和 HTTP。
/tmp
此目录由需要临时存储文件的程序使用。
/tmp存储在 /tmp 中的数据不保证在系统重启后仍然存在。例如,它取决于 /etc/tmpfiles.d/tmp.conf 中进行的设置。
/usr
/usr 与用户无关,而是 Unix 系统资源的首字母缩写。 /usr 中的数据是静态的、只读的数据,可以在符合 文件系统层次结构标准 (FHS) 的各种主机之间共享。此目录包含所有应用程序,包括 GNOME 等图形桌面,并在文件系统中建立一个辅助层次结构。 /usr 包含多个子目录,例如 /usr/bin、/usr/sbin、/usr/local 和 /usr/share/doc。
/usr/bin
包含通用可访问的程序。
/usr/sbin
包含系统管理员专用的程序,例如修复功能。
/usr/local
在此目录中,系统管理员可以安装本地的、与发行版无关的扩展。
/usr/share/doc
包含各种文档文件和您系统的发行说明。在 manual 子目录中可以找到本手册的在线版本。如果安装了多种语言,此目录可能包含不同语言的手册版本。
在 packages 下可以找到您系统上安装的软件包中包含的文档。对于每个软件包,都会创建一个子目录 /usr/share/doc/packages/PACKAGENAME,其中通常包含软件包的 README 文件,有时还有示例、配置文件或其他脚本。
如果您的系统上安装了 HOWTO,/usr/share/doc 还包含 howto 子目录,其中可以找到有关 Linux 软件设置和操作的许多任务的附加文档。
/var
/usr 保存静态、只读数据,而 /var 用于在系统操作期间写入的数据,因此是可变数据,例如日志文件或假脱机数据。有关 /var/log/ 下可以找到的最重要日志文件的概述,请参阅 表 21.1,“日志文件”。
/windows
仅当您的系统上同时安装了 Microsoft Windows 和 Linux 时才可用。包含 Windows 分区上可用的 Windows 数据。您是否可以编辑此目录中的数据取决于您的 Windows 分区使用的文件系统。如果是 FAT32,您可以打开和编辑此目录中的文件。对于 NTFS,openSUSE Leap 还包括写入访问支持。但是,NTFS-3g 文件系统的驱动程序功能有限。
Shell 脚本提供了一种方便的方式来执行各种任务:收集数据、在文本中搜索单词或短语以及其他有用的事情。以下示例显示了一个打印文本的小型 shell 脚本
在运行此脚本之前,需要满足一些先决条件
每个脚本都应该包含一个 Shebang 行(如上例所示)。如果缺少此行,则需要手动调用解释器。
您可以将脚本保存在任何位置。但是,最好将其保存在 shell 可以找到的目录中。shell 中的搜索路径由环境变量 PATH 确定。普通用户对 /usr/bin 没有写入权限。因此,建议将脚本保存在用户目录 ~/bin/ 中。上述示例将命名为 hello.sh。
脚本需要可执行权限。使用以下命令设置权限
> chmod +x ~/bin/hello.sh如果您满足了上述所有先决条件,您可以通过以下方式执行脚本
作为绝对路径。 脚本可以使用绝对路径执行。在我们的例子中,它是 ~/bin/hello.sh。
任何地方。 如果 PATH 环境变量包含脚本所在的目录,您可以使用 hello.sh 执行脚本。
每个命令可以使用三个通道,用于输入或输出
标准输出。 这是默认输出通道。每当命令打印内容时,它都使用标准输出通道。
标准输入。 如果命令需要来自用户或其他命令的输入,它将使用此通道。
标准错误。 命令使用此通道进行错误报告。
要重定向这些通道,有以下几种可能性
命令 > 文件
将命令的输出保存到文件中,现有文件将被删除。例如,ls 命令将其输出写入文件 listing.txt
> ls > listing.txt命令 >> 文件
将命令的输出附加到文件中。例如,ls 命令将其输出附加到文件 listing.txt
> ls >> listing.txt命令 < 文件
将文件作为给定命令的输入读取。例如,read 命令将文件内容读入变量中
> read a < foo命令1 | 命令2
将左侧命令的输出重定向作为右侧命令的输入。例如,cat 命令输出 /proc/cpuinfo 文件的内容。此输出由 grep 用于仅过滤包含 cpu 的行
> cat /proc/cpuinfo | grep cpu每个通道都有一个文件描述符:0(零)用于标准输入,1用于标准输出,2用于标准错误。允许在 < 或 > 字符之前插入此文件描述符。例如,以下行搜索以 foo 开头的文件,但通过将其重定向到 /dev/null 来抑制其错误。
> find / -name "foo*" 2>/dev/null别名是一个或多个命令的快捷定义。别名的语法是
alias NAME=DEFINITION
例如,以下行定义了一个别名 lt,它输出长列表(选项 -l),按修改时间排序(-t),并以反向排序顺序打印(-r)。
> alias lt='ls -ltr'要查看所有别名定义,请使用 alias。使用 unalias 和相应的别名名称删除您的别名。
Shell 变量可以是全局的或局部的。全局变量,或环境变量,可以在所有 shell 中访问。相反,局部变量仅在当前 shell 中可见。
要查看所有环境变量,请使用 printenv 命令。如果您需要知道变量的值,请将变量名称作为参数插入
> printenv PATH变量,无论是全局的还是局部的,也可以用 echo 查看。
> echo $PATH要设置局部变量,请使用变量名,后跟等号,再后跟值
> PROJECT="SLED"不要在等号周围插入空格,否则会出错。要设置环境变量,请使用 export
> export NAME="tux"要删除变量,请使用 unset。
> unset NAME下表包含您可以在 shell 脚本中使用的常用环境变量
|
|
当前用户的家目录 |
|
|
当前主机名 |
|
|
当工具本地化时,它使用此环境变量中的语言。英语也可以设置为 |
|
|
shell 的搜索路径,由冒号分隔的目录列表 |
|
|
指定在每个命令之前打印的正常提示符 |
|
|
指定在执行多行命令时打印的辅助提示符 |
|
|
当前工作目录 |
|
|
当前用户 |
例如,如果您有脚本 foo.sh,您可以这样执行它
> foo.sh "Tux Penguin" 2000要访问传递给脚本的所有参数,您需要位置参数。这些参数包括 $1 用于第一个参数,$2 用于第二个参数,依此类推。您最多可以有九个参数。要获取脚本名称,请使用 $0。
以下脚本 foo.sh 打印从 1 到 4 的所有参数
#!/bin/sh echo \"$1\" \"$2\" \"$3\" \"$4\"
如果使用上述参数执行此脚本,您将得到
"Tux Penguin" "2000" "" ""
变量替换将模式应用于变量内容的左侧或右侧。以下列表包含可能的语法形式
${VAR#pattern}
从左侧删除最短的匹配项
>file=/home/tux/book/book.tar.bz2>echo ${file#*/} home/tux/book/book.tar.bz2
${VAR##pattern}
从左侧删除最长的匹配项
>file=/home/tux/book/book.tar.bz2>echo ${file##*/} book.tar.bz2
${VAR%pattern}
从右侧删除最短的匹配项
>file=/home/tux/book/book.tar.bz2>echo ${file%.*} /home/tux/book/book.tar
${VAR%%pattern}
从右侧删除最长的匹配项
>file=/home/tux/book/book.tar.bz2>echo ${file%%.*} /home/tux/book/book
${VAR/pattern_1/pattern_2}
用 PATTERN_2 替换 VAR 中 PATTERN_1 的内容
>file=/home/tux/book/book.tar.bz2>echo ${file/tux/wilber} /home/wilber/book/book.tar.bz2
Shell 允许您连接和分组命令以进行条件执行。每个命令都会返回一个退出代码,该代码决定其操作的成功或失败。如果为 0(零),则命令成功,其他任何值都表示特定于命令的错误。
以下列表显示了如何对命令进行分组
命令1 ; 命令2
按顺序执行命令。不检查退出代码。以下行用 cat 显示文件内容,然后用 ls 打印其文件属性,无论它们的退出代码如何。
> cat filelist.txt ; ls -l filelist.txt命令1 && 命令2
如果左侧命令成功(逻辑与),则运行右侧命令。以下行显示文件内容并仅在前面的命令成功时打印其文件属性(与此列表中的前一个条目进行比较)
> cat filelist.txt && ls -l filelist.txt命令1 || 命令2
当左侧命令失败时运行右侧命令(逻辑或)。以下行仅在创建 /home/tux/foo 目录失败时才在 /home/wilber/bar 中创建目录
> mkdir /home/tux/foo || mkdir /home/wilber/barfuncname(){ ... }
创建一个 shell 函数。您可以使用位置参数来访问其参数。以下行定义函数 hello 来打印一条简短消息
> hello() { echo "Hello $1"; }您可以这样调用此函数
> hello Tux它会打印
Hello Tux
为了控制脚本的流程,shell 具有 while、if、for 和 case 结构。
if 命令用于检查表达式。例如,以下代码测试当前用户是否是 Tux
if test $USER = "tux"; then echo "Hello Tux." else echo "You are not Tux." fi
测试表达式可以尽可能复杂或简单。以下表达式检查文件 foo.txt 是否存在
if test -e /tmp/foo.txt ; then echo "Found foo.txt" fi
测试表达式也可以用方括号缩写。
if [ -e /tmp/foo.txt ] ; then echo "Found foo.txt" fi
在 https://bash.cyberciti.biz/guide/If..else..fi 查找更多有用的表达式。
有关 Bash 的重要信息可在手册页 man bash 中找到。有关此主题的更多信息,请参阅以下列表
https://tldp.cn/LDP/Bash-Beginners-Guide/html/index.html — Bash 初学者指南
https://tldp.cn/HOWTO/Bash-Prog-Intro-HOWTO.html — BASH 编程 - 介绍 HOW-TO
https://tldp.cn/LDP/abs/html/index.html — 高级 Bash 脚本指南
https://www.grymoire.com/Unix/Sh.html — Sh - Bourne Shell