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

本文介绍了在Linux环境中如何使用env命令为脚本选择合适的解释器,并解释了env的作用及不同场景下的应用。
#!/usr/bin/env
在linux的一些bash的脚本,需在开头一行指定脚本的解释程序,如:
#!/usr/bin/env python
再如:
#!/usr/bin/env perl
#!/usr/bin/env zimbu
#!/usr/bin/env ruby
但有时候也用
#!/usr/bin/python

#!/usr/bin/perl
那么 env到底有什么用?何时用这个呢?
    脚本用env启动的原因,是因为脚本解释器在linux中可能被安装于不同的目录,env可以在系统的PATH目录中查找。同时,env还规定一些系统环境变量。
如我系统里env程序执行后打印结果:
[root@int-test bin]# env
rvm_bin_path=/usr/local/rvm/bin
HOSTNAME=int-test
GEM_HOME=/usr/local/rvm/gems/ruby-1.9.3-p484
SHELL=/bin/bash
TERM=linux
HISTSIZE=1000
IRBRC=/usr/local/rvm/rubies/ruby-1.9.3-p484/.irbrc
OLDPWD=/
MY_RUBY_HOME=/usr/local/rvm/rubies/ruby-1.9.3-p484
USER=root
LD_LIBRARY_PATH=:/usr/local/lib:/usr/local/lib:/usr/local/lib
LS_COLORS=rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:mi=01;05;37;41:su=37;41:sg=30;43:ca=30;41:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arj=01;31:*.taz=01;31:*.lzh=01;31:*.lzma=01;31:*.tlz=01;31:*.txz=01;31:*.zip=01;31:*.z=01;31:*.Z=01;31:*.dz=01;31:*.gz=01;31:*.lz=01;31:*.xz=01;31:*.bz2=01;31:*.tbz=01;31:*.tbz2=01;31:*.bz=01;31:*.tz=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.rar=01;31:*.ace=01;31:*.zoo=01;31:*.cpio=01;31:*.7z=01;31:*.rz=01;31:*.jpg=01;35:*.jpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;35:*.svg=01;35:*.svgz=01;35:*.mng=01;35:*.pcx=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.m2v=01;35:*.mkv=01;35:*.ogm=01;35:*.mp4=01;35:*.m4v=01;35:*.mp4v=01;35:*.vob=01;35:*.qt=01;35:*.nuv=01;35:*.wmv=01;35:*.asf=01;35:*.rm=01;35:*.rmvb=01;35:*.flc=01;35:*.avi=01;35:*.fli=01;35:*.flv=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.yuv=01;35:*.cgm=01;35:*.emf=01;35:*.axv=01;35:*.anx=01;35:*.ogv=01;35:*.ogx=01;35:*.aac=01;36:*.au=01;36:*.flac=01;36:*.mid=01;36:*.midi=01;36:*.mka=01;36:*.mp3=01;36:*.mpc=01;36:*.ogg=01;36:*.ra=01;36:*.wav=01;36:*.axa=01;36:*.oga=01;36:*.spx=01;36:*.xspf=01;36:
_system_type=Linux
rvm_path=/usr/local/rvm
rvm_prefix=/usr/local
MAIL=/var/spool/mail/root
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin:/opt/svn/bin
PWD=/home/git/gitlab-shell/bin
LANG=en_US.UTF-8
_system_arch=x86_64
_system_version=6
HISTCONTROL=ignoredups
rvm_version=1.25.6 (stable)
SHLVL=1
HOME=/root
LOGNAME=root
CVS_RSH=ssh
GEM_PATH=/usr/local/rvm/gems/ruby-1.9.3-p484:/usr/local/rvm/gems/ruby-1.9.3-p484@global
LESSOPEN=|/usr/bin/lesspipe.sh %s
install_flag=1
RUBY_VERSION=ruby-1.9.3-p484
_system_name=CentOS
G_BROKEN_FILENAMES=1
_=/bin/env

可以用env来执行程序:

zhouhh@zhh64:~$ env python
Python 2.6.6 (r266:84292, Sep 15 2010, 16:22:56)
[GCC 4.4.5] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>>
而如果直接将解释器路径写死在脚本里,可能在某些系统就会存在找不到解释器的兼容性问题。有时候我们执行一些脚本时就碰到这种情况。

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


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
/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-
     preter by searching through the directories specified by PATH.

           #!/usr/bin/env perl

     One limitation of that example is that it assumes the user's value for
     PATH is set to a value which will find the interpreter you want to exe-
     cute.  The -P option can be used to make sure a specific list of directo-
     ries is used in the search for utility.  Note that the -S option is also
     required for this example to work correctly.

           #!/usr/bin/env -S -P/usr/local/bin:/usr/bin perl

     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:

           #!/usr/bin/env -S-P/usr/local/bin:/usr/bin:${PATH} perl

这种写法主要是为了让你的程序在不同的系统上都能适用。
不管你的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会好些,当然更好的是

#!/usr/bin/env -S-P/usr/local/bin:/usr/bin:${PATH} php


转自:http://selfcontroller.iteye.com/blog/2012385

<think>我们正在处理用户的问题:如何正确执行shell脚本,特别是当文件开头使用`#! /usr/bin/env xdg-open`时出现错误。 根据用户描述,他们可能在尝试通过双击桌面图标或直接执行脚本来运行一个图形界面的程序,但使用了`xdg-open`作为解释器,这通常是不正确的。 分析问题: 1. 用户脚本开头使用了`#!/usr/bin/env xdg-open`,这行代码的目的是指定脚本的解释器。但是,`xdg-open`是一个用于打开文件或URL的命令,它根据文件的类型调用相应的程序(比如用默认浏览器打开html文件,用图片查看器打开图片等)。它不是一个脚本解释器(如bash、sh、python等)。 2. 因此,当用户试图执行这个脚本时,系统会尝试用`xdg-open`来“解释”这个脚本文件,而`xdg-open`会把这个脚本文件当作一个普通文件(比如文本文件)打开,而不是执行它。这通常会导致错误,因为脚本需要被解释器执行,而不是被打开。 解决方案: 1. 如果这是一个shell脚本(以.sh结尾),那么应该使用bash或其他shell作为解释器。正确的shebang应该是: ```bash #!/usr/bin/env bash#!/bin/bash ``` 2. 如果这是一个其他类型的脚本(比如Python),则应该使用对应的解释器。 另外,用户提到“运行失败”,可能还涉及权限问题。因此,我们还需要确保脚本具有可执行权限。 步骤: 1. 修改脚本的shebang,使用正确的解释器。 2. 给脚本添加可执行权限:`chmod +x 脚本文件名` 3. 如果用户希望双击桌面图标来运行脚本,那么应该创建一个.desktop文件(桌面快捷方式),并在其中指定执行脚本的命令,而不是在脚本里使用`xdg-open`。 参考引用[3]中,我们可以看到.desktop文件的例子,其中`Exec`字段指定了要执行的命令(脚本的路径),并且可以设置`Terminal`字段来决定是否打开终端。 因此,具体步骤为: 步骤1:修改脚本文件 - 打开脚本文件,将第一行改为正确的shebang(例如,对于bash脚本:`#!/usr/bin/env bash`) - 保存文件 步骤2:修改脚本权限 - 在终端中,切换到脚本所在目录,运行命令:`chmod +x 脚本文件名` 步骤3:如果用户是通过桌面图标运行,那么应该创建一个.desktop文件(如果还没有的话),并在其中正确设置: - `Exec`字段:指向脚本的绝对路径(例如:`Exec=/path/to/your_script.sh`) - 如果需要显示终端输出,可以设置`Terminal=true`,否则`Terminal=false` - 注意:不要在脚本中使用`#!/usr/bin/env xdg-open`,因为脚本本身应该被解释器执行,而不是被打开。 如果用户已经有一个.desktop文件,那么修改这个.desktop文件,确保`Exec`字段指向脚本,并且脚本的开头是正确解释器。 示例: 假设用户有一个脚本`hello_world.sh`,内容如下: ```bash #!/usr/bin/env bash echo "Hello World" read -p "Press enter to continue" ``` 然后,创建一个桌面文件`hello_world.desktop`,内容如下: ``` [Desktop Entry] Version=1.0 Type=Application Terminal=true # 如果不需要终端,可以设置为false Exec=/path/to/hello_world.sh Name=Hello World Comment=This is my script Icon=/path/to/icon.png ``` 这样,双击桌面图标时,就会执行该脚本(如果Terminal=true,则会在终端中运行)。 注意:用户之前错误地在脚本中使用了`#!/usr/bin/env xdg-open`,这会导致系统试图用`xdg-open`打开这个脚本文件,从而可能用文本编辑器打开,而不是执行。所以必须修改脚本的shebang。 另外,引用[2]中提到,shell脚本的基本语法中指定解释器的方式是`#!/usr/bin/env bash`。 总结:用户的问题在于脚本的解释器指定错误,应该改为正确的解释器,并设置可执行权限,同时确保.desktop文件(如果使用的话)正确指向脚本。 相关问题: 1. 如何为不同类型的脚本指定正确的shebang? 2. 如何创建桌面快捷方式(.desktop文件)来运行脚本? 3. 为什么需要给脚本添加可执行权限?还有哪些权限设置? 4. 如何让脚本在终端中运行并显示输出?</think>### 如何正确执行 Shell 脚本脚本开头使用 `#!/usr/bin/env xdg-open` 导致错误时,问题在于 **`xdg-open` 不是脚本解释器**,而是用于打开文件的工具。以下是正确执行脚本的步骤: #### 1. **修正 Shebang 行(关键步骤)** - **错误用法**:`#!/usr/bin/env xdg-open`(试图用文件打开工具执行脚本) - **正确用法**: - **Shell 脚本**:`#!/usr/bin/env bash` 或 `#!/bin/bash` - **Python 脚本**:`#!/usr/bin/env python3` - **Node.js 脚本**:`#!/usr/bin/env node` - 示例: ```bash # 正确修改脚本第一行 #!/usr/bin/env bash # 改为对应解释器 echo "Hello World" ``` #### 2. **添加可执行权限** ```bash chmod +x 脚本文件名.sh # 赋予执行权限 ``` - 权限修改后,文件图标通常会变化(如显示为可执行程序)[^1] #### 3. **通过终端执行脚本** ```bash # 方式1:绝对路径执行 /path/to/脚本文件名.sh # 方式2:相对路径执行(需先进入脚本目录) ./脚本文件名.sh ``` #### 4. **桌面图标启动(可选)** 若需双击桌面图标运行: 1. 创建 `.desktop` 文件(如 `myapp.desktop`) 2. 内容示例: ```ini [Desktop Entry] Type=Application Exec=/path/to/脚本文件名.sh # 指向脚本绝对路径 Name=我的脚本 Icon=/path/to/图标.png Terminal=true # 需要显示终端时设为true ``` 3. 将此文件放入 `~/.local/share/applications/` 或 `/usr/share/applications/` --- ### 错误原因解析 - **`xdg-open` 的作用**:根据文件类型调用默认程序(如用文本编辑器打开 `.txt`,用浏览器打开 `.html`)。当用于脚本时,它会尝试用文本编辑器打开脚本文件而非执行[^3]。 - **正确逻辑链**: ```mermaid graph LR A[双击图标] --> B[.desktop文件] B --> C[Exec命令执行脚本] C --> D[脚本的Shebang指定解释器] D --> E[系统调用bash/node/python等] ``` --- ### 常见问题解决 1. **报错 `Permission denied`** → 执行 `chmod +x 脚本名` 2. **报错 `Command not found`** → 检查 Shebang 路径是否正确(如 `#!/usr/bin/env bash`) 3. **双击图标无反应** → 在 `.desktop` 文件中添加 `Terminal=true` 查看错误输出 4. **依赖问题** → 在脚本开头声明环境变量: ```bash #!/usr/bin/env bash export PATH="/自定义路径:$PATH" # 添加自定义搜索路径[^1] ``` ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值