#! /usr/bin/env 脚本解释程序的作用

Posted by baicai on May 11, 2017

#!/usr/bin/env 

在linux的一些bash的脚本,需在开头一行指定脚本的解释程序,如: 
<pre>#!/usr/bin/env python </pre>再如: 
<pre>#!/usr/bin/env perl 
#!/usr/bin/env zimbu 
#!/usr/bin/env ruby </pre>但有时候也用 
<pre>#!/usr/bin/python </pre>和 
<pre>#!/usr/bin/perl </pre>那么 env到底有什么用?何时用这个呢? 
    脚本用env启动的原因,是因为脚本解释器在linux中可能被安装于不同的目录,env可以在系统的PATH目录中查找。同时,env还规定一些系统环境变量。 
如我系统里env程序执行后打印结果: 
<pre>mac@macmbp ~> env Apple_PubSub_Socket_Render=/private/tmp/com.apple.launchd.WHGWRJgv3D/Render HOME=/Users/mac LANG=zh_CN.UTF-8 LOGNAME=mac PATH=/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/go/bin PWD=/Users/mac SHELL=/bin/bash SHLVL=1 SSH_AUTH_SOCK=/private/tmp/com.apple.launchd.NSsrdPru5h/Listeners TERM=xterm-256color TERM_PROGRAM=Apple_Terminal TERM_PROGRAM_VERSION=388.1 TERM_SESSION_ID=13ADC3CB-DE48-4ADE-B9AB-0BF0E5D45454 TMPDIR=/var/folders/ml/b32sv3j51m99nh7xvczpn81r0000gn/T/ USER=mac XPC_FLAGS=0x0 XPC_SERVICE_NAME=0 __CF_USER_TEXT_ENCODING=0x1F5:0x19:0x34 __fish_bin_dir=/usr/local/Cellar/fish/2.2.0/bin __fish_datadir=/usr/local/Cellar/fish/2.2.0/share/fish __fish_help_dir=/usr/local/Cellar/fish/2.2.0/share/doc/fish __fish_sysconfdir=/usr/local/Cellar/fish/2.2.0/etc/fish</pre>可以用env来执行程序: 
<pre>mac@macmbp ~> env ruby -v ruby 2.3.4p301 (2017-03-30 revision 58214) [x86_64-darwin16]
</pre>而如果直接将解释器路径写死在脚本里,可能在某些系统就会存在找不到解释器的兼容性问题。有时候我们执行一些脚本时就碰到这种情况。 

话说,vim作者Bram Moolenaar推出了一种脚本语言叫zimbu,放在google code上。 
地址:http://code.google.com/p/zimbu/ 
下载编译后,执行它的示例程序,报错: 


<pre>zhouhh@zhh64:~/zimbu$ cat hello.zu 
#!/usr/bin/env zimbush 
FUNC int MAIN() 
  IO.write(“Hello World!\n”) 
  RETURN 0 

zhouhh@zhh64:~/zimbu$ ./hello.zu </pre>/usr/bin/env: zimbush: 没有那个文件或目录 
显然没有设置环境变量。 

Probably the most common use of env is to find the correct interpreter 
     for a script, when the interpreter may be in different directories on 
     different systems.  The following example will find the perl' inter-&nbsp;</span><br style="font-family: Helvetica, Tahoma, Arial, sans-serif;"><span style="font-family: Helvetica, Tahoma, Arial, sans-serif;">&nbsp;&nbsp;&nbsp;&nbsp; preter by searching through the directories specified by PATH.&nbsp;</span><br style="font-family: Helvetica, Tahoma, Arial, sans-serif;"><br style="font-family: Helvetica, Tahoma, Arial, sans-serif;"><pre><span style="font-family: Helvetica, Tahoma, Arial, sans-serif;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #!/usr/bin/env perl&nbsp;</span></pre><br style="font-family: Helvetica, Tahoma, Arial, sans-serif;"><span style="font-family: Helvetica, Tahoma, Arial, sans-serif;">&nbsp;&nbsp;&nbsp;&nbsp; One limitation of that example is that it assumes the user's value for&nbsp;</span><br style="font-family: Helvetica, Tahoma, Arial, sans-serif;"><span style="font-family: Helvetica, Tahoma, Arial, sans-serif;">&nbsp;&nbsp;&nbsp;&nbsp; PATH is set to a value which will find the interpreter you want to exe-&nbsp;</span><br style="font-family: Helvetica, Tahoma, Arial, sans-serif;"><span style="font-family: Helvetica, Tahoma, Arial, sans-serif;">&nbsp;&nbsp;&nbsp;&nbsp; cute.&nbsp; The -P option can be used to make sure a specific list of directo-&nbsp;</span><br style="font-family: Helvetica, Tahoma, Arial, sans-serif;"><span style="font-family: Helvetica, Tahoma, Arial, sans-serif;">&nbsp;&nbsp;&nbsp;&nbsp; ries is used in the search for utility.&nbsp; Note that the -S option is also&nbsp;</span><br style="font-family: Helvetica, Tahoma, Arial, sans-serif;"><span style="font-family: Helvetica, Tahoma, Arial, sans-serif;">&nbsp;&nbsp;&nbsp;&nbsp; required for this example to work correctly.&nbsp;</span><br style="font-family: Helvetica, Tahoma, Arial, sans-serif;"><br style="font-family: Helvetica, Tahoma, Arial, sans-serif;"><pre><span style="font-family: Helvetica, Tahoma, Arial, sans-serif;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #!/usr/bin/env -S -P/usr/local/bin:/usr/bin perl&nbsp;</span></pre><br style="font-family: Helvetica, Tahoma, Arial, sans-serif;"><span style="font-family: Helvetica, Tahoma, Arial, sans-serif;">&nbsp;&nbsp;&nbsp;&nbsp; The above finds perl’ only if it is in /usr/local/bin or /usr/bin.  That 
     could be combined with the present value of PATH, to provide more flexi- 
     bility.  Note that spaces are not required between the -S and -P options: 

<pre>           #!/usr/bin/env -S-P/usr/local/bin:/usr/bin:${PATH} perl </pre>
这种写法主要是为了让你的程序在不同的系统上都能适用。 
不管你的perl是在/usr/bin/perl还是/usr/local/bin/perl,#!/usr/bin/env perl会自动的在你的用户PATH变量中所定义的目录中寻找perl来执行的。 

还可以加上-P参数来指定一些目录去寻找perl这个程序, 
#!/usr/bin/env -S -P/usr/local/bin:/usr/bin perl的作用就是在/usr/local/bin和/usr/bin目录下寻找perl。 
为了让程序更加的有可扩展性,可以写成 
#!/usr/bin/env -S-P/usr/local/bin:/usr/bin:${PATH} perl,那么它除了在这两个目录寻找之外,还会在PATH变量中定义的目录中寻找。 

同样的php也适用, #!/usr/bin/php写成 
#!/usr/bin/env php会好些,当然更好的是 
<pre>#!/usr/bin/env -S-P/usr/local/bin:/usr/bin:${PATH} php</pre><p></p>