在UNIX/Linux中,經(jīng)常需要寫腳本執(zhí)行自動化工作。執(zhí)行腳本有多種方式,可以通過sh,source或者exec。這些方式有一些區(qū)別,需要根據(jù)需求選擇合適的方式。
sh方式
使用$ sh script.sh執(zhí)行腳本時,當(dāng)前shell是父進程,生成一個子shell進程,在子shell中執(zhí)行腳本。腳本執(zhí)行完畢,退出子shell,回到當(dāng)前shell。
$ ./script.sh與$ sh script.sh等效。
例子
使用loop.sh腳本反復(fù)打印當(dāng)前進程號。
$ vi loop.sh
#!/bin/sh
while [ 1 = 1 ]; do
echo $$
sleep 1
done
查看父shell的進程號,是2454。
$ echo $$
2454
在loop.sh中,打印子shell進程號,是2700。
$ sh loop.sh
2700
2700
使用htop監(jiān)控進程樹。父進程2454生成了子進程2700,在子進程中執(zhí)行腳本。

source方式
使用$ source script.sh方式,在當(dāng)前上下文中執(zhí)行腳本,不會生成新的進程。腳本執(zhí)行完畢,回到當(dāng)前shell。
source方式也叫點命令,$ . script.sh與$ source script.sh等效。注意在點命令中,.與script.sh之間有一個空格。
$ source loop.sh
2454
2454
$ . ~/loop.sh
2454
2454
使用htop監(jiān)控進程樹。在進程2454中直接執(zhí)行腳本。

man source解釋source在當(dāng)前shell環(huán)境中執(zhí)行腳本。
source filename [arguments]
Read and execute commands from filename in the current shell environment and
return the exit status of the last command executed from filename.
exec方式
使用exec command方式,會用command進程替換當(dāng)前shell進程,并且保持PID不變。執(zhí)行完畢,直接退出,不回到之前的shell環(huán)境。
查看當(dāng)前shell的進程號為2364。

使用exec打印進程號,進程號不變,還是2364。打印完畢,直接退出shell。
riversec@rcs:~$ exec echo $$
2364
Connection to 192.168.2.123 closed.
man exec解釋exec替代當(dāng)前shell,執(zhí)行腳本。
exec [-cl] [-a name] [command [arguments]]
If command is specified, it replaces the shell. No new process is created.
The arguments become the arguments to command.
使用sh和source方式對上下文的影響
在sh和source方式下,腳本執(zhí)行完畢,都會回到之前的shell中。但是兩種方式對上下文的影響不同呢。
此例中,jump.sh腳本執(zhí)行如下操作:1)跳到/,2)打印當(dāng)前工作目錄,3)打印Hello。
$ vi jump.sh
#!/bin/sh
cd /
pwd
echo Hello
通過sh執(zhí)行腳本時,修改的上下文不會影響當(dāng)前shell。jump.sh退出以后,工作目錄保持不變。
$ pwd
/home/riversec
$ ./jump.sh
/
Hello
$ pwd
/home/riversec
通過source執(zhí)行腳本時,修改的上下文會影響當(dāng)前shell。jump.sh退出以后,當(dāng)前工作目錄變成了/。
$ pwd
/home/riversec
$ source jump.sh
/
Hello
$ pwd
/