Command not found when running Bash script, but works when running command directly
By default, shell functions are only available in the shell they were defined in; they're not inherited by subprocesses. Your .bash_profile is only run by the login shell, not shells that run as subprocesses (e.g. to run scripts).
Option 1: In bash, you can run
export -f letsencrypt_webfaction
in the defining shell (i.e. in your .bash_profile), and it'll be inherited by subprocesses (provided they're also running bash).Option 2: You can define the function in your .bashrc instead of .bash_profile, and since you run .bashrc from .bash_profile it'll get defined in all your bash shells.
Option 3: Just use the full command in the script. This would be my preference, since it makes the script more independent. Having a script depend on a shell function that's defined in a completely different place is fragile (as you're experiencing) and just a bit weird.
While I'm at it, here are some general scripting recommendations:
In most contexts, you should put double-quotes around variable references (and strings that contain variable references) to avoid weird effects from word splitting and wildcard expansion. The right side of an assignment is one place it's ok to leave them off (e.g.
PATH=$PATH:$HOME/bin
andPATH="$PATH:$HOME/bin"
are both ok), but I tend to recommend using quotes everywhere as it's hard to keep track of where it's safe to leave them off and where it's dangerous. For the same reason, you should almost always use"$@"
instead of$*
(as in theletsencrypt_webfaction
function).shellcheck.net is really good at spotting errors like this, so I recommend running your shell scripts through it and acting on its suggestions.
Using the
function
keyword to define a function is nonstandard; the standard syntax is to use()
after the function name, like this:letsencrypt_webfaction() {
PATH="$PATH:$GEM_HOME/bin" GEM_HOME="$HOME/.letsencrypt_webfaction/gems" RUBYLIB="$GEM_HOME/lib" ruby2.2 "$HOME/.letsencrypt_webfaction/gems/bin/letsencrypt_webfaction" "$@"
}The function I just gave still may not work right, since it (re)defines
GEM_HOME
after using it. The entire line gets parsed (and pre-existing variable definitions expanded), then the variables defined as prefixes to the command get included in the environment of the command. This means that the ruby script gets the updated value ofGEM_HOME
, but the updated values ofPATH
andRUBYLIB
are based on whatever valueGEM_HOME
had when the function was run. I'm pretty sure this is not what you intended.In the restart apache script, you use a relative path to the
restart
command. This will be evaluated relative to the working directory of the process that runs the script, not relative to the script's location. This could be anywhere.
Script gives if: command not found
I can solve this by using do eval "$HI"
. Of course, the problem is that if I use double quotes, then expansions are done at the first run. I don't want it to be expanded, but evaluated at every run.
EDIT: I got around this by using \$
, or even better, using single quotes (this did mean I had to escape all the single quotes though).
EDIT 2: After consideration, I just decided to use functions without eval
-- dealing with escaping was not worth it.
Bash script prints Command Not Found on empty lines
Make sure your first line is:
#!/bin/bash
Enter your path to bash if it is not /bin/bash
Try running:
dos2unix script.sh
That wil convert line endings, etc from Windows to unix format. i.e. it strips \r (CR) from line endings to change them from \r\n (CR+LF)
to \n (LF)
.
More details about the dos2unix
command (man page)
Another way to tell if your file is in dos/Win format:
cat scriptname.sh | sed 's/\r/<CR>/'
The output will look something like this:
#!/bin/sh<CR>
<CR>
echo Hello World<CR>
<CR>
This will output the entire file text with <CR>
displayed for each \r
character in the file.
How to handle command not found in bash
Insert this before your first echo
line if you use bash >= 4.0:
command_not_found_handle() { echo "not found"; return 127; }
And then insert this after your last echo
line to get rid of this function:
unset command_not_found_handle
Output, e.g.:
...RVM Version : not found
...Node Version : v4.2.6
...Ruby Version : ruby 2.3.1p112 (2016-04-26) [x86_64-linux-gnu]
...Bundler Version : not found
...Passenger Version: not found
zsh: command not found: ng
Possibly, on startup bash adds ng location to PATH
, but zsh doesn't. You can check ~/.bashrc
and ~/.bashprofile
to see what is added to the PATH
variable (all lines starting with export...
), and copy these lines to ~/.zshrc
file.
Related Topics
How to Search Contents of Multiple PDF Files
How Pthread_Mutex_Lock Is Implemented
How to Get Position of Cursor in Terminal
Remove a Symlink to a Directory
Removing Part of a Filename for Multiple Files on Linux
Mongodb Gui Client (Cross-Platform or Linux)
Why Linux/Gnu Linker Chose Address 0X400000
Linux X64: Why Does R10 Come Before R8 and R9 in Syscalls
How to Get 'Find' to Ignore .Svn Directories
Merge PDF's with PDFtk with Bookmarks
How Is the Linux Kernel Tested
Self Modifying Code Always Segmentation Faults on Linux
Why Doesn't "Total" from Ls -L Add Up to Total File Sizes Listed
Linux Bash Script to Extract Ip Address