Linux腳本中究竟如何指定解析程序?

背景

在使用shell腳本或者Python腳本的時候,有的人喜歡使用#!/usr/bin/env NAME指定解析程序,而有的人喜歡使用#!/usr/bin/NAME,前者每每被認爲兼容性更好,因此應該優先使用,本文將仔細分析下這種寫法的利弊。shell

分析

首先,能夠仔細看下env命令的手冊,這裏咱們只節選開頭部分bash

NAME
       env - run a program in a modified environment

SYNOPSIS
       env [OPTION]... [-] [NAME=VALUE]... [COMMAND [ARG]...]

能夠看到,使用env這種方式指定你的解析程序的時候,系統會在PATH環境變量中查找對應的解析程序,當系統中有不一樣的解析程序版本的時候能夠經過設置PATH環境變量的方式去指定優先使用某個版本,還有,若是你的腳本會被移植到不通的系統中去,可移植性也會更好。
可是,任何事物都有兩面性,使用#!/usr/bin/env NAME去指定解析程序也不例外。
設想一種狀況,你在系統中安裝了一個名字叫program-a的解析程序,放在了/directory-a目錄下,而後將系統環境變量PATH修改成:
PATH=/directory-a:$PATH
而後你在腳本中使用#!/usr/bin/env program-a指定解析程序,後面另外一位同事在不知情的狀況下,在這臺服務器上也安裝了一個叫作program-a的解析程序(版本不一樣,或者更甚功能也有很大差別),放在了/directory-b下,而且將PATH修改成:
PATH=/directory-b:$PATH
這樣的話若是你的腳本就有可能由於使用了錯誤的解析程序而失效。
還有一種常見的狀況,在Linux中使用crontab命令添加週期性任務的時候,若是這個任務是本身寫的一個腳本,並且在腳本中使用了#!/usr/bin/env NAME指定解析程序的話,也存在出錯的風險,由於crontab默認只使用頗有限的環境變量,可使用cat /etc/crontab查看當前系統中crontab的默認配置服務器

$cat /etc/crontab
SHELL=/bin/bash
PATH=/sbin:/bin:/usr/sbin:/usr/bin
MAILTO=root

# For details see man 4 crontabs

# Example of job definition:
# .---------------- minute (0 - 59)
# |  .------------- hour (0 - 23)
# |  |  .---------- day of month (1 - 31)
# |  |  |  .------- month (1 - 12) OR jan,feb,mar,apr ...
# |  |  |  |  .---- day of week (0 - 6) (Sunday=0 or 7) OR sun,mon,tue,wed,thu,fri,sat
# |  |  |  |  |
# *  *  *  *  * user-name  command to be executed

這樣的話,若是你使用env指定你的解析程序,而這個解析程序又剛好不在crontab配置的PATH環境變量路徑中的話就有可能致使你的任務出錯。code

總結

使用#!/usr/bin/env NAME的方式指定解析程序並不必定是好的,你得先考慮清楚本身的腳本在什麼樣的環境中運行,會不會被移植到其它系統,或者你的腳本會被crontab執行的話,就要注意本身的解析程序是否在crontab的環境變量中。crontab

相關文章
相關標籤/搜索