Open byodian opened 2 years ago
赋值语法 foo=bar
,访问变量中存储的数值,其语法为 $foo
。使用空格分隔赋值语句,导致不能正常工作。在 Shell 脚本中使用空格会起到分割参数的作用。
# 此语句不能正常工作
foo = bar
Bash 中的字符串通过 '
和 ''
分隔符来定义。但含义却不同,
'
定义的字符串是原义字符串,其中的变量不会被转义。''
定义的字符串会就变量值进行替换。foo=bar
echo "$foo"
# 打印 bar
echo '$foo'
# 打印 $foo
bash 使用了很多特殊变量表示参数、错误代码和相关变量。
$0
脚本名$1~$9
$1代表第1个参数,一次类推。$@
所有参数$#
参数个数$?
前一个命令到返回值$$
当前脚本进程识别码!!
上一条命令$_
上一条命令的最后一个参数STDOUT
返回输出值STDERR
返回错误及错误码&&
和 ||
;
分隔true
返回码永远是 0
false
返回码永远是 1
以变量的形式获取一个命令的输出
$( CMD )
执行 CMD
命令,输出结果会替换掉 $( CMD )
bashuser~$ echo "We are in $(pwd)"
We are in /home/bashuser
<( CMD )
会执行 CMD
并将结果输出到一个临时文件中,并将 <( CMD )
替换成临时文件名。
返回值会通过文件而不是 STDIN。
显示文件夹 foo
和 bar
中文件的区别。
bashuser~$ diff <(ls foo) <(ls bar)
?
*
{}
Bash is the GNU shell, when the shell is started, it reads its configuration files. The most important are:
/etc/profile
~/.bash_profile
~/.bashrc
export PATH="$PATH:~/scripts"
脚本应该具有执行权限,更改文件权限使用命令:
chmod +x script_name.sh
# 脚本所在的文件夹没有被加入环境变量时
./script_name.sh
# 指定特殊的 shell 执行脚本
sh script_name.sh
bash script_name.sh
这种执行方式会建立一个 subshell。脚本中的函数、变量和 aliases 只能在此 subshell 中访问到,当 subshell 退出并且父级 shell 获取到控制权后,脚本中所有的内容都会被清空,并且忘记脚本所做的更改。
如果你不想开始一个新的 shell 而是希望这个脚本在当前 shell 中被打开,你应该使用:
source script_name.sh
此命令不需要脚本具有执行权限,命令可以在当前环境中被执行。这时脚本中定义的变量,在当前环境中就可以被访问到。
$ source script.sh
执行脚本的命令中,添加 -x
选项将会 debug 整个脚本文件
bash -x script_name.sh
在脚本文件的某一命令行前后添加 set -x
和 set +x
即可 debug 该命令行。
set -x # activate debugging from here
set +x # stop debugging from here
在你的代码中插入 echo 语句,这会帮助你辨别错误在哪里发生并且变量的值是什么
#!/bin/bash
echo "Value of variable x is: $x"
set -e
option通过使用 set -e
选项,在遇到错误时,脚本会立即结束执行。通过这种方式也可以帮助我们快速发现问题。
/etc/profile
/etc/bashrc
You might also find that /etc/profile on your system only holds shell environment and program startup settings, while /etc/bashrc
contains system-wide definitions for shell functions and aliases. The /etc/bashrc
file might be referred to in /etc/profile
or in individual user shell initialization files.
This is the preferred configuration file for configuration user environment individually. In this file, users can add extra configuration options or change default settings:
~/.bash_profile 不存在时,此文件会被读取
~/.bash_profile 和 ~/.bash_login 不存在时,此文件会被读取。
现在开发环境下,不需要登陆的 shell 是比较常见的,在这种 shell
中,用户不需要提供用户名和密码。此时 bash 会读取 ~/.bashrc 配置文件。
lsb_release -a
检查 linux 发行版本
cat /etc/shells
查询 linux 系统中的支持的 shell 类型
umask
查看用户掩码,系统为了保护用户创建文件和文件夹的权限,此时系统会有一个默认的用户掩码(umask),大多数的 linux 系统的默认掩码为 022。
用户掩码的作用:用户在创建文件时从文件的默认权限中减去掩码中的权限,默认权限(文件 0666,文件夹 0777)- umask
创建文件的权限为:0666 - 0022 = 0644
文件夹的权限为: 0777 - 0022 = 0755
umask -S
以符号的形式查看用户掩码
-rw-r--r-- 12 linuxize users 12.0K Apr 8 20:51 filename.txt
|[-][-][-]- [------] [---]
| | | | | | |
| | | | | | +-----------> 7. Group
| | | | | +-------------------> 6. Owner
| | | | +--------------------------> 5. Alternate Access Method
| | | +----------------------------> 4. Others Permissions
| | +-------------------------------> 3. Group Permissions
| +----------------------------------> 2. Owner Permissions
+------------------------------------> 1. File Type
r
(read) = 4w
(write) - 2x
(execute) = 1In case you're curious, this is how you would copy a file under WSL to your Windows clipboard:
cat report.txt | clip.exe
Shell 脚本基础的概念是一系列命令的列表,列表中的命令按照顺序执行。结构良好的 Shell 脚本还应该有注释(使用前置符号
#
)描述步骤。Shell 脚本文件扩展以
.sh
结尾,文件开头使用shebang
构造提示系统一个 shell 脚本将要开始。Shell 毕竟是一门真正的编程语言,所以 Shell 脚本应该由变量、控制结构等完成。但不论 shell 脚本如何复杂,它都是一系列按照顺序执行的命令集合。
The shell is, after all, a real programming language, complete with variables, control structures, and so forth. No matter how complicated a script gets, it is still just a list of commands executed sequentially.
可以在执行命令的同时向程序传递参数:
执行步骤
也就是说,个参数中如果存在空格会被当做多个参数处理,使用以下任意一种方式可以使用带空格参数:
\
转义Shell 如何寻找
date
和echo
等命令?类似与 Python 或 Ruby,Shell 是一个编程环境,它具备变量、条件、循环或函数。
当执行命令时,实际上我们是在执行一段 shell 可以解释执行的简短代码。在 shell 中执行某条指令,它会咨询环境变量
$PATH
,并列出进行程序搜索的路径:在
$PATH
中搜索由: 所分割的一系列目录,基于名字搜索该程序。找到就执行该程序。确定某个指令名所代表的程序,可以使用
which
命令。导航
shell 中的路径是一组被分割的目录,在 Linux 系统中使用
/
分割,Windows 中用\
分割。绝对路径以
/
开头,相对路径是指相对于当前工作目录的路径。配置 Shell 提示符
显示各种有用的信息
Shell 程序中的流概念
数据流重定向(redirect),将数据传到给其他地方。在 Shell 中,程序有两个主要的流:输入流和输出流。
<
或<<
>
(替换)或>>
(追加)2>
(替换)或2>>
(追加)数据流重定向的作用
将 stdout 与 stderr 分别存到不同的文件夹
以上两个文件的建立方式
dev/null 垃圾桶设备与特殊写法
如果我知道错误讯息会发生,所以要将错误讯息忽略掉而不显示或储存呢?
/dev/null
可以吃掉任何导向这个设备的信息喔将正确与错误数据通通写入同一个文件
standard input
<
将原本需要由键盘输入的数据,改由文件内容来取代<<
表示结束的输入字符,举例我们要用cat
直接将输入的信息输出到 catfile 中,且当键盘输入 eof 时,该输入就会结束,此时与>
做对比,<
输入需要使用快捷键 crtl + d 结束输入。命令执行的判断依据
;
连续执行$?
(指令回传值) 与&&
或||
指令执行结果正确,回传一个 $? = 0
指令执行结果错误,回传一个 $? ≠ 0
命令是一个一个执行,
command1 && command2 || command3
管道命令
管道命令仅能处理经由前面一个命令传来的正确信息,也就是标准输出的信息,对于标准错误并没有直接处理的能力。
command1 | command2 | command3
在每个管道命令后面接的第一个数据必定是命令,而这个命令必须要能够接受标准输入的数据才行,这样的命令才可以是管道命令。例如,less、head、tail、more 等都是可以接受 STDOUT,而 ls、cp、mv 则不是
!/bin/sh
#
在 shell 中代表注释,而!
具有特殊的含义。References