How can I set the PATH on Ubuntu in a way where its variables that I set are also set in a post-receive script? Currently I'm doing it via the ~/.bashrc
file like this:
export PATH="$PATH:/opt/mssql-tools/bin"
but can't see any change in the PATH
if I print it from the hook. Therefore, if I try to execute the command in question in the hook, I get
remote: FileNotFoundError: [Errno 2] No such file or directory: 'sqlcmd': 'sqlcmd'
So the only solution I see right now is defining it again in the post-receive hook itself, like this:
export PATH="$PATH:/opt/mssql-tools/bin"
Is there a better way?
Thank you!
First, a small bit of file setup:
$ mkdir /tmp/dir1 /tmp/dir2
$ date > /tmp/dir1/foo
$ date > /tmp/dir2/bar
Now, consider a simple script:
$ chmod 755 foo.sh; cat foo.sh
#!/bin/sh
# intentionally set an inadequate PATH:
export PATH=""
# script to 'ls' two dirs, show that output, and show the diff of the two.
ls /tmp/dir1 > temp1
ls /tmp/dir2 > temp2
echo /tmp/dir1:
cat temp1
echo /tmp/dir2:
cat temp2
diff temp1 temp2
The script is well-formed syntactically, but let's see what happens:
$ ./foo.sh
./foo.sh: ls: not found
./foo.sh: ls: not found
/tmp/dir1:
./foo.sh: cat: not found
/tmp/dir2:
./foo.sh: cat: not found
./foo.sh: diff: not found
The path isn't sufficient for the script interpreter to find the executables the script wants to run. Three separate executables fail to load: ls
, cat
, and diff
. So let's help it a little. Since ls
typically resides in the /bin
directory, let's edit PATH
to become:
export PATH="/bin"
and try again:
$ ./foo.sh
/tmp/dir1:
foo
/tmp/dir2:
bar
./foo.sh: diff: not found
Well, ls
runs okay now. That's progress. And since cat
also lives in /bin, adding /bin to the path killed two birds with one stone. But diff
still isn't being found, because diff
lives in /usr/bin. So let's add that to the PATH:
export PATH="/bin:/usr/bin"
and try again:
$ ./foo.sh
/tmp/dir1:
foo
/tmp/dir2:
bar
1c1
< foo
---
> bar
Voila! No more errors, because the PATH
variable contains everything needed to allow the script interpreter to locate the executables that are called by the script.
The other way is to tell PATH
to butt out and specify your own path to executables. This method is sometimes handy when you might not trust or desire the "standard" executables, for whatever reason. When structuring a script in this fashion, I prefer to use variables for the executables I want to reference, so that if^H^Hwhen the location changes, I can just change the variables and don't have to search the entire script for all the invocations of that executable.
$ chmod 755 bar.sh; cat bar.sh
#!/bin/sh
# intentionally set an inadequate PATH:
export PATH=""
# ls lives in /bin:
LS="/bin/ls"
# so does cat:
CAT="/bin/cat"
# but diff lives in /usr/bin:
DIFF="/usr/bin/diff"
# script to 'ls' two dirs, show that output, and show the diff of the two.
$LS /tmp/dir1 > temp1
$LS /tmp/dir2 > temp2
echo /tmp/dir1:
$CAT temp1
echo /tmp/dir2:
$CAT temp2
$DIFF temp1 temp2
And the output:
$ ./bar.sh
/tmp/dir1:
foo
/tmp/dir2:
bar
1c1
< foo
---
> bar
You can mix and match these approaches, by specifying a PATH
that includes most things, and specifying absolute paths for the others, but your problem is arising because you have not done that.
You either need to specify a full and adequate PATH
in your hook script, and/or specify absolute paths to the remaining executables (if any) that reside outside whatever PATH
variable your hook script currently uses.