#! – 告诉系统其后路径所指定的程序即是解释此脚本文件的 Shell 程序。(#!/bin/bash)
- 运行 Shell 脚本有两种方法
- 作为可执行程序
chmod +x ./test.sh #使脚本具有执行权限 ./test.sh #执行脚本 注意,一定要写成 ./test.sh,而不是 test.sh,运行其它二进制的程序也一样,直接写 test.sh, linux 系统会去 PATH 里寻找有没有叫 test.sh 的, 而只有 /bin, /sbin, /usr/bin,/usr/sbin 等在 PATH 里, 你的当前目录通常不在 PATH 里,所以写成 test.sh 是会找不到命令的,要用 ./test.sh 告诉系统说,就在当前目录找。
- 作为解释器参数
这种运行方式是,直接运行解释器,其参数就是 shell 脚本的文件名,如: /bin/sh test.sh 这种方式运行的脚本,不需要在第一行指定解释器信息,写了也没用。
- 作为可执行程序
source命令用法
source FileName
作用:在当前 bash 环境下读取并执行 FileName 中的命令。该 filename 文件可以无 "执行权限"。
注:该命令通常用命令 . 来替代。
sh、bash的命令用法:
sh FileName 或 bash FileName
作用:打开一个子 shell 来读取并执行 FileName 中命令。该 filename 文件可以无 "执行权限"。
注:运行一个shell脚本时会启动另一个命令解释器。
./ 的命令用法:
./FileName
作用: 打开一个子 shell 来读取并执行 FileName 中命令,该 filename 文件需要 "执行权限"。
注:运行一个 shell 脚本时会启动另一个命令解释器。
fork、source、exec
- 使用fork方式运行script时, 就是让shell(parent process)产生一个child process去执行 该script,
当child process结束后,会返回parent process,但parent process的环境是 不会因child process的改变而改变的。
- 使用source方式运行script时, 就是让script在当前process内执行, 而不是产生一个 child process来执行。
由于所有执行结果均于当前process内完成,若script的环境有所改变, 当然也会改变当前process环境了。
- 使用exec方式运行script时, 它和source一样,也是让script在当前process内执行,但是process内的原代码剩下部分将被终止。
同样,process内的环境随script改变而改变。
通常如果我们执行时,都是默认为fork的。
参数说明
我们可以在执行 Shell 脚本时,向脚本传递参数,脚本内获取参数的格式为:$n。n 代表一个数字, $0 为执行的文件名;$1 为执行脚本的第一个参数,2 为执行脚本的第二个参数,以此类推……
参数处理 说明
$# 传递到脚本的参数个数
$* 以一个单字符串显示所有向脚本传递的参数。 如"$*"用「"」括起来的情况、以"$1 $2 … $n"的形式输出所有参数。
$$ 脚本运行的当前进程ID号
$! 后台运行的最后一个进程的ID号
$@ 与$*相同,但是使用时加引号,并在引号中返回每个参数。如"$@"用「"」括起来的情况、以"$1" "$2" … "$n" 的形式输出所有参数。
$- 显示Shell使用的当前选项,与set命令功能相同。
$? 显示最后命令的退出状态。0表示没有错误,其他任何值表明有错误。
$* 与 $@ 区别:
相同点:都是引用所有参数。
不同点:只有在双引号中体现出来。
假设在脚本运行时写了三个参数 1、2、3,,则 " * " 等价于 "1 2 3"(传递了一个参数),而 "@" 等价于 "1" "2" "3"(传递了三个参数)。
test.sh para1 para2 para3
$0 $1 $2 $3
$0是脚本名称,$1,2是参数;
$# 参数个数
输入/输出重定向
- 在 Linux 中,所有的内容都是文件,计算机硬件也是文件,标准输入设备(键盘)和标准输出设备(显示器)也是文件
- Linux 是使用设备文件名来表示硬件的(比如 /dev/sda1 就代表第一块 SATA 硬盘的第一个主分区), 但是键盘和显示器的设备文件名并不好记忆,我们用”0”、”1”、”2”来分别代表标准输入、标准输出和标准错误输出
- 输出重定向指的是改变输出方向,不再输出到屏幕上,而是输出到文件他设备中 输入重定向则是指不再使用键盘作为输入设备,而是把文件的内容作为命令的输入
设 备 设备文件名 文件描述符 类 型
键盘 /dev/stdin 0 标准输入
显示器 /dev/stdout 1 标准输出
显示器 /dev/stderr 2 标准错误输出
命令 说明
command > file 把命令的正确输出重定向到 file。
command < file 将输入重定向到 file。
command >> file 将输出以追加的方式重定向到 file。
错误命令 2 > file 以覆盖的方式,把命令的错误输出输出到指定的文件或设备中
错误命令 2 >> file 以追加的方式,把命令的错误输出输出到指定的文件或设备中
command &> file =command > file 2>&1 以覆盖的方式,把正确输出和错误输出都保存到同一个文件中
command &>> file =command >> file 2>&1 以追加的方式,把正确输出和错误输出都保存到同一个文件中
command > filename 2>errfilename 把正确输出和错误输出分别保存到不同文件中
n > file 将文件描述符为 n 的文件重定向到 file。
n >> file 将文件描述符为 n 的文件以追加的方式重定向到 file。
n >& m 将输出文件 m 和 n 合并。
n <& m 将输入文件 m 和 n 合并。
<< tag 将开始标记 tag 和结束标记 tag 之间的内容作为输入。
需要注意的是文件描述符 0 通常是标准输入(STDIN),1 是标准输出(STDOUT),2 是标准错误输出(STDERR)
如果希望将 stdout 和 stderr 合并后重定向到 file,可以这样写:
$ command > file 2>&1
或者 $ command >> file 2>&1
如果希望对 stdin 和 stdout 都重定向,可以这样写:
$ command < file1 >file2
Here Document
Here Document 是 Shell 中的一种特殊的重定向方式,用来将输入重定向到一个交互式 Shell 脚本或程序。
它的基本的形式如下:
command << delimiter
document
delimiter
它的作用是将两个 delimiter 之间的内容(document) 作为输入传递给 command。
注意:
结尾的delimiter 一定要顶格写,前面不能有任何字符,后面也不能有任何字符,包括空格和 tab 缩进。
开始的delimiter前后的空格会被忽略掉。
/dev/null 文件
如果希望执行某个命令,但又不希望在屏幕上显示输出结果,那么可以将输出重定向到 /dev/null:
$ command > /dev/null
/dev/null 是一个特殊的文件,写入到它的内容都会被丢弃;如果尝试从该文件读取内容,那么什么也读不到。
但是 /dev/null 文件非常有用,将命令的输出重定向到它,会起到"禁止输出"的效果。
如果希望屏蔽 stdout 和 stderr,可以这样写:
$ command > /dev/null 2>&1
必须是2>&1,如果改成1>&2,仍然是标准输出;
su
su name: 使用nologin shell 执行/etc/bashrc,~/.bashrc
su - name 使用login shell 执行/etc/profile ,/etc/bashrc,/etc/.bash_profile ~/.bashrc
()
(cmd) 表示在子shell中执行;cmd是在当前shell中执行;
当前shell中定义的变量,子shell读不到;
`` vs $()
``和$():功能相同,优先执行包含的命令