You may notice that most shell and Perl script starts with the following line:
Let us find out why is it a good idea to use #!/usr/bin/env bash instead of #!/bin/bash as shebang?
#!/usr/bin/env As a Shebang
The #! is called a shebang. It consists of a number sign and an exclamation point character (#!), followed by the full path to the interpreter such as /bin/bash. All scripts under Linux, *BSD, macOS, and Unix-like system execute using the interpreter specified on a first line. However, there is a small problem. BASH or Perl is not always in the same location (PATH) such as /bin/bash or /usr/bin/perl. If you want to make sure that script is portable across different UNIX like operating systems you need to use /usr/bin/env command as shebang.
Make Linux/Unix Script Portable With #!/usr/bin/env As a Shebang
The env command allows to run a program in a modified environment. First, find line
For example here is a small bash shell script:
#!/usr/bin/env bash x=5 y=10 echo "$x and $y"
The advantage of #!/usr/bin/env bash is that it will use whatever bash executable appears first in the running user’s $PATH variable. If you have two version of bash installed as follows and PATH set to /home/vivek/bin:/usr/local/bin:/usr/bin:/bin:/usr/games/bin:/bin:/usr/bin, than bash4 will execute the script:
- /bin/bash # <-- bash3
- /usr/local/bin/bash # <-- bash4
Using env in the shebang of a script
env is a shell command for Unix-like operating systems. We can use it for various purposes. For example:
- Display a list of environment variables
- Run another command in a modified environment
- Add or remove variables
- Change the value of existing variables
To show current environment variables defined by your shell, run env command:
We can filter out infromation using the grep command/egrep command as follows:
env | grep HOME
env | egrep 'HOME|USER|VERSION|SHELL|PWD'
SHELL=/bin/bash GNOME_SHELL_SESSION_MODE=ubuntu PWD=/tmp HOME=/home/vivek USERNAME=vivek VTE_VERSION=6003 USER=vivek OLDPWD=/tmp
Let us see some more examples.
#!/usr/bin/env perl use warnings; print "Hello " x 5; print "\\n";
#!/usr/bin/env python x=10 y=20 z=x+y print z
Another example with python3:
#!/usr/bin/env python3 import boto3 t = boto3.resource('s3') for b in t.buckets.all(): print(b.name)
Is env always located at /usr/bin/env
env is /usr/bin/env
Some info from various *nix systems:
ShellCheck is a static analysis tool for shell scripts. One can use it to finds bugs in your shell scripts. It is written in Haskell. You can find warnings and suggestions for bash/sh shell scripts with this tool. Let us see how to install and use ShellCheck on a Linux or Unix-like system to enhance your shell scripts, avoid errors and productivity.
I just made my Linux/Unix script portable with #!/usr/bin/env. The env-mechanism is hugely enhancing convenience, and almost all Unix like systems today provide /usr/bin/env. I regular use FreeBSD, CentOS/RHEL/Ubuntu/Debian/SUSE Linux, macOS, and OpenBSD and all of them provided /usr/bin/env by default. Now you do not have to search for a program via the PATH environment variable. It makes the script more portable. Also, note that it is not a foolproof method. Always make sure you have /usr/bin/env exists or use a soft link/symbolic link to point it to correct path for env command. Moreover, your work or script looks more professional with this simple hack. See env command man page (documentation) or type the following man command:
$ man bash
$ man env
🐧 28 comments so far... add one ↓
|Category||List of Unix and Linux commands|
|Disk space analyzers||df • ncdu • pydf|
|File Management||cat • tree|
|Firewall||Alpine Awall • CentOS 8 • OpenSUSE • RHEL 8 • Ubuntu 16.04 • Ubuntu 18.04 • Ubuntu 20.04|
|Network Utilities||NetHogs • dig • host • ip • nmap|
|OpenVPN||CentOS 7 • CentOS 8 • Debian 10 • Debian 8/9 • Ubuntu 18.04 • Ubuntu 20.04|
|Package Manager||apk • apt|
|Processes Management||bg • chroot • cron • disown • fg • jobs • killall • kill • pidof • pstree • pwdx • time|
|Searching||grep • whereis • which|
|User Information||groups • id • lastcomm • last • lid/libuser-lid • logname • members • users • whoami • who • w|
|WireGuard VPN||Alpine • CentOS 8 • Debian 10 • Firewall • Ubuntu 20.04|