Let us presume the following:
In a certain folder you have some scripts. They are not meant to be globally accessible and are meant to write their resulting files into the folder they sit in.
To make it more easy, you not use a way to capture the path where the script sits, and you not use a path but only the filename for the resulting file names the script will create.
For now let's assume a simple downloading script:
Code: Select all
#!/bin/bash
# https://example.com/watch/myseries-dub-episode-1.html
wget -c "https://example.com/watch/myseries-dub-episode-1.mp4" -O "My Series 01.mp4" && notify-send -i info -t 0 "Downloading 1" "finished" || notify-send -i error -t 0 "Downloading 1" "failed"
wget -c "https://example.com/watch/myseries-dub-episode-2.mp4" -O "My Series 02.mp4" && notify-send -i info -t 0 "Downloading 2" "finished" || notify-send -i error -t 0 "Downloading 2" "failed"
echo ▓▓▓ press enter / return ▓▓▓
read
and it all sits in, let's say, "/mnt/sda2/video/My Series/" as wget.sh and is executable and readable for user guest.
Now there are more than one ways to execute this script. Would all ways lead to the same results? and would at least one way lead to unexpected consequences when the script was slightly different?
The first, and to me most obvious way executing this script is:
Open a guest terminal
Code: Select all
guest@rava:/ $cd "/mnt/sda2/video/My Series/"
or
Code: Select all
guest@rava:/ $cd /mnt/sda2/video/My\ Series/
and execute it like so:
Code: Select all
guest@rava:/mnt/sda2/video/My Series $ ./wget.sh
No issues there, the script will work as long as it is bug-free, and it will save its files [presuming the URLs you gave it are valid (which in my example case are not)] - in this case the resulting videos like so:
Code: Select all
/mnt/sda2/video/My Series/My Series 01.mp4
/mnt/sda2/video/My Series/My Series 02.mp4
Now, another way executing a script or program not in your $PATH is by its full name. Let's presume you are in /etc and you do this:
Code: Select all
guest@rava:/etc $ "/mnt/sda2/video/My Series/wget.sh"
It would execute the script okay, but the script would try writing the files into /etc and guest should have no right to write into /etc resulting in an error.
Another way executing a script not in your $PATH is like so:
Code: Select all
guest@rava:/mnt/sda2/video/My Series $ . wget.sh
In the above example, that would work okay as well. You are in the correct target folder after all.
Still, the last technique executing a script can lead to unexpected consequences. Not with how the example script is coded.
But let's assume your script is more complex and it checks certain conditions. Like exiting with an error code and a message when started as user root. Or exiting with an error code and a message when
not started as user root. Or it is checking for any other conditions that are needed; e.g. it relies on certain programs, let's say it converts images and uses mogrify for that: no mogrify, the script cannot work.
To check for the availability of mogrify, you can have a
Code: Select all
if [ ! test if condition X is met ]; then
echo "$scriptname: condition X is NOT met! Aborting!"
exit 1
fi
The " ! test if condition X is met " is example code to illustrate a test, it is like this not a working bash or sh script code.
Now when that test would trigger because its condition is not met, what would happen?
This part
Code: Select all
echo "$scriptname: condition X is NOT met! Aborting!"
exit 1
would be executed.
What would happen when you executed the script as
Code: Select all
guest@rava:/mnt/sda2/test/test1 $ . test1.sh
?
Since it runs "as the shell itself" (to put it in layman's terms) and not in an new instance of the shell as it would be when executed like so
Code: Select all
guest@rava:/mnt/sda2/test/test1 $ ./test1.sh
the "exit 1" would be executed by the shell itself, and without the ability to read the error message the terminal window or the tab in the terminal window will close.
Since that is what you told the shell to do. When you did a previous "su -" in that terminal, then it would only exit the current root instance of the shell and the one that started the "su -" instance is back in session. In this case you could see the error, but when there is only one instance of bash started in that terminal or in that tab of a terminal, you will not see an error and only the closing of that window or that tab.
And I presume that is not what you want the script to to. Let us use the shell itself to create a test script and make it executable and execute it:
Code: Select all
guest@rava:/tmp$ echo '#!/bin/bash
> if [ true ] ; then
> echo Dummy Condition not met. Exiting.
> exit 1
> fi
> echo all is well, normal execution.
> ' >test.sh
guest@rava:/tmp$ cat test.sh
#!/bin/bash
if [ true ] ; then
echo Dummy Condition not met. Exiting.
exit 1
fi
echo all is well, normal execution.
guest@rava:/tmp$ chmod a+x test.sh
guest@rava:/tmp$ ./test.sh
Dummy Condition not met. Exiting.
guest@rava:/tmp$ echo $?
1
guest@rava:/tmp$
All is well when you execute it like "
./test.sh" and it returns the return value of "1" just like you told it to.
I cannot show you what it looks like when executing that script as "
. test.sh" since that would only close the current tab of my xfce4-terminal.
But I can use "su -" to create a new instance of the shell, a root instance, and since the script can be executed by everyone, root shall execute it like "
. test.sh":
Code: Select all
guest@rava:/tmp$ su -
Password:
root@rava:~# cd /tmp/
root@rava:/tmp# . test.sh
Dummy Condition not met. Exiting.
guest@rava:/tmp$ echo $?
1
guest@rava:/tmp$
As you can see, I am back as user guest since the executing of "
. test.sh" executed "exit 1" in the very instance of the root-bash itself, and thus the root instance of the shell exited with the given error code of "1".
Therefore, the usual way you should execute a script not in your path is by moving into the folder the script itself sits in and execute it like
Cave!
And yet another issue with using ". /path/to/file" without much thought: Executed like this will execute any kind of file, or trying to, even plain text files not meant as program or scripts. In the best case scenario your shell will only complain, but in the worst case code would be executed not meant to be executed and that could create more or less serious issues.
So best only use ". /path/to/file" when you know what you are doing and when there is a reason why that /path/to/file should be executed in the very shell instance itself.
Like when updating your aliases+functions file and giving it a test-run.
HTH!