在UNIX/Linux
中,經常需要寫腳本執行自動化工作。執行腳本有多種方式,可以通過sh
,source
或者exec
。這些方式有一些區別,需要根據需求選擇合適的方式。
sh方式
使用$ sh script.sh
執行腳本時,當前shell是父進程,生成一個子shell進程,在子shell中執行腳本。腳本執行完畢,退出子shell,回到當前shell。
$ ./script.sh
與$ sh script.sh
等效。
例子
使用loop.sh
腳本反復打印當前進程號。
$ 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
監控進程樹。父進程2454
生成了子進程2700
,在子進程中執行腳本。
source方式
使用$ source script.sh
方式,在當前上下文中執行腳本,不會生成新的進程。腳本執行完畢,回到當前shell。
source
方式也叫點命令,$ . script.sh
與$ source script.sh
等效。注意在點命令中,.
與script.sh
之間有一個空格。
$ source loop.sh
2454
2454
$ . ~/loop.sh
2454
2454
使用htop
監控進程樹。在進程2454
中直接執行腳本。
man source
解釋source在當前shell環境中執行腳本。
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
進程替換當前shell進程,并且保持PID
不變。執行完畢,直接退出,不回到之前的shell環境。
查看當前shell的進程號為2364
。
使用exec
打印進程號,進程號不變,還是2364
。打印完畢,直接退出shell。
riversec@rcs:~$ exec echo $$
2364
Connection to 192.168.2.123 closed.
man exec
解釋exec替代當前shell,執行腳本。
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
方式下,腳本執行完畢,都會回到之前的shell中。但是兩種方式對上下文的影響不同呢。
此例中,jump.sh
腳本執行如下操作:1)跳到/
,2)打印當前工作目錄,3)打印Hello
。
$ vi jump.sh
#!/bin/sh
cd /
pwd
echo Hello
通過sh
執行腳本時,修改的上下文不會影響當前shell。jump.sh
退出以后,工作目錄保持不變。
$ pwd
/home/riversec
$ ./jump.sh
/
Hello
$ pwd
/home/riversec
通過source
執行腳本時,修改的上下文會影響當前shell。jump.sh
退出以后,當前工作目錄變成了/
。
$ pwd
/home/riversec
$ source jump.sh
/
Hello
$ pwd
/