getting permission to execute a bash script - bash

im trying to get my server to execute a simple bash script:
#!/bin/bash
echo Hello World
After saving this to /var/www/script (im saving it to the web directory for no reason in particular) i try and execute it with
exec /var/www/script
This fails returning i don't have permission to execute it, sudo exec isn't a thing so i do sudo -i then run exec /var/www/script as root and i still have permission denied. I fairly uncertain why executing it as root doesn't work. Im wondering if i'm
A) using the wrong command to execute a bash script
B) have incorrect formatting in the script
C) shouldn't have saved it to /var/www/
D) done some other thing that i'm not even aware of.
Im running ubuntu server 16.04 if that helps.

File Permissions
First, make sure that you have the correct file permissions:
chmod +x /var/www/script_name #Gives the current user execute permissions
Executing Your Bash Script
In order to execute your bash script, the easiest option is to just simply call it (without any additional commands) by typing in the relative path to the script:
/var/www/script_name
There are other options for explicitly executing your script from the shell (in your case, use the bash shell to execute your script as a bash script). From TLDP documentation...
A script can also explicitly be executed by a given shell, but generally we only do this if we want to obtain special behavior, such as checking if the script works with another shell or printing traces for debugging:
rbash script_name.sh # Execute using the restricted bash shell
sh script_name.sh # Execute using the sh shell
bash -x script_name.sh # Execute using the bash shell
A Note on File Extensions: "Shebang" line > File extension
It is not an advised practice to use file extensions with your scripts, especially if you think your code may evolve beyond its current functionality.
Just in case you were wondering if the file extension may be your problem... it is not. It is important that you know that the file extension of a script isn't necessary at all. What matter is what you put in the "shebang" line:
To use the sh shell:
#!/bin/sh
To use the bash shell:
#!/bin/bash
It won't matter what file extension you use - the "shebang" line indicates what shell will be used to execute the script. You could save a script with the "shebang" of #!/bin/bash as script_name.py, but it would remain a bash script. If you attempt to execute it, ./script_name.py, it would be executed as a bash script.
As #Arjan mentioned in the comments, using file extensions for your script could lead to unnecessary complications if you decide to change the implementation of your project (i.e., a different shell / language):
I could decide later to shift my project to sh, python, perl, C, etc. Perhaps because I want to add functionality. Perhaps because I want to make it portable to a system without bash. It would be much more difficult if I used the .sh file extension, since then I'd need to change all my references to the script just because I changed its implementation.

You have two choices:
Run it as an argument to bash:
bash /var/www/script
Alternatively, set the execute bit:
chmod +x /var/www/script
And, now you can execute it directly:
/var/www/script

Related

Running executables without ./ or bash or source

I am learning the basics of bash and linux. To execute a script, I could type...
bash script1
or
source script1
or
./script1
The first two will run without chmod u+x and the last one requires it.
From my understanding, bash tries to run things in a subshell so it doesn't mess things up. When I add bash before the filename, it's executed in a subshell. source is just a way of telling the computer to run it in the current shell. I'm not sure why these don't require the execute permission though.
./ is pretty straightforward. However, I've seen people run scripts without the ./. One told me I could do this by doing something with PATH. I completely don't understand this PATH thing.
Can someone explain in the easiest way possible?
On
bash script1
you are executing bash (the one that needs execution permission) to read and process script1 (which needs read permission).
On
source script1
you are telling the current bash to read the file and process it as if it were typed on the current shell, so the current bash reads the script (read permission) and executes every line.
Finally, on
./script1
you are telling bash to try to run a file called ./script1, so it checks if it is executable (execute permission on ./script1) and passes this file to the kernel to be executed. The kernel opens the file and acts as needed (if it have a shebang line, it uses whatever is given, if it finds it is an ELF object, it prepares the binary in memory...).
Regarding PATH, check some documentation and come back with specific doubts, if any.
PATH is environmental variable. It is a list containing all directories that will be searched when you issue a command. So if your PATH is defined as PATH=/bin:/usr/bin these two dirs will be searched, if you redefine it as export PATH=./:$PATH it will also add current directory to search list.

How to create a AS400 shell script (.ksh) file

I am new to shell script on iSeries, but i have created one sample script:
#!/bin/ksh
cd /QIBM/Userdata/employeedetails/
pwd
ls -ltr
I placed it under /QIBM/testscript.ksh and tried to run the script on the main menu using STRQSH CMD('/QIBM/testscript.ksh')
I got this error, can someone please let me know what did do wrong here?
qsh: 001-0014 Command /QIBM/testscript.ksh not found.
Press ENTER to end terminal session.
I am wondering, is it possible to create shell script on the iSeries (AS/400)?
It is certainly possible to create a shell script.
The default shell is Qshell which can be referenced as /bin/qsh or /bin/sh.
echo '#!/bin/sh
pwd
ls -ltr' > $HOME/testscript.sh
To run it:
STRQSH CMD('$HOME/testscript.sh')
Korn shell is available with IBM PASE for i at /qopensys/usr/bin/sh or /qopensys/usr/bin/ksh.
Also I would advise against putting things in the /QIBM directory. I suggest $HOME or /opt. See the Filesystem Hierarchy Standard for more information.
Did you make the script executable? Unless you have *ALLOBJ authority, you must mark the script executable by executing either
chmod 755 /QIBM/testscript.ksh from a shell or
CHGAUT OBJ('/QIBM/testscript.ksh') USER(USRNAME) DTAAUT(*RWX) from CL
It also looks like you maybe forgot the # in the first line, unless it's just a Stack Overflow formatting mistake. Your first line should be:
#!/QOpenSys/usr/bin/ksh
as ksh is not found in /bin on IBM i.

Understanding script language

I'm a newbie to scripting languages trying to learn bash programming.
I have very basic question. Suppose I want to create three folders like $HOME/folder/
with two child folders folder1 and folder2.
If I execute command in shell like
mkdir -p $HOME/folder/{folder1,folder2}
folder will be created along with child folder.
If the same thing is executed through script I'm not able get expected result. If sample.sh contains
#!/bin/sh
mkdir -p $HOME/folder/{folder1,folder2}
and I execute sh ./sample.sh, the first folder will be created then in that a single {folder1,folder2} directory is created. The separate child folders are not created.
My query is
How the script file works when we compared to as terminal command? i.e., why is it not the same?
How to make it work?
bash behaves differently when invoked as sh, to more closely mimic the POSIX standard. One of the things that changes is that brace expansion (which is absent from POSIX) is no longer recognized. You have several options:
Run your script using bash ./sample.sh. This ignores the hashbang and explicitly uses bash to run the script.
Change the hashbang to read #!/bin/bash, which allows you to run the script by itself (assuming you set its execute bit with chmod +x sample.sh).
Note that running it as sh ./sample.sh would still fail, since the hashbang is only used when running the file itself as the executable.
Don't use brace expansion in your script. You could still use as a longer method for avoiding duplicate code:
for d in folder1 folder2; do
mkdir -p "$HOME/folder/$d"
done
Brace expansion doesn't happen in sh.
In sh:
$ echo {1,2}
produces
{1,2}
In bash:
$ echo {1,2}
produces
1 2
Execute your script using bash instead of using sh and you should see expected results.
This is probably happening because while your tags indicate you think you are using Bash, you may not be. This is because of the very first line:
#/bin/sh
That says "use the system default shell." That may not be bash. Try this instead:
#!/usr/bin/env bash
Oh, and note that you were missing the ! after #. I'm not sure if that's just a copy-paste error here, but you need the !.

How to run cd within bash script (outside of subshell)

I am writing a bash script (called gotodir.sh) and would like to change directories during the course of the script, depending on some variables, say cd /home/username/${FOO}/${BAR}.
Just running this as is doesn't work when the process exits, since the directory was changed in the subshell only.
My shell is tcsh. (Yeah, I know... not my choice here.) In my .cshrc file, I want to alias the keyword gotodir to gotodir.sh.
I have read that executing the script with a . or source prefix will cause the script to be run in the same shell (i.e. not a subshell).
I have tried putting the following in my .cshrc file:
alias gotodir . /home/username/bin/gotodir.sh
but this results in the error: /bin/.: Permission denied.
I have also tried using source instead of .
alias gotodir source /home/username/bin/gotodir.sh
but this results in the error: if: Expression Syntax.
How do I accomplish this using a bash script while running tcsh?
When you source a file from tcsh, it tcsh runs the commands. The #! is ignored as a comment because you're not running the file as a script, just reading commands from it as if they'd been entered at the shell prompt.
Your mission is doomed to failure. Only a tcsh cd command can change the current directory of a tcsh process.
But if you're willing to bend a little, you can write a script which runs as a separate process and outputs the name of the directory to cd to. Then set the alias like
alias gotodir 'cd `/blah/blah/thescript`'
Addendum
Adding an argument is possible, but tricky. Alias arguments look like history expansion, with !:1 expanding to the first argument. But quotes don't protect the ! character. You have to backslash it to prevent it being expanded during creation of the aliase, so it can do its work during the execution of the alias.
alias gotodir 'cd `/blah/blah/thescript \!:1`'
Additional quoting may be required to handle arguments and directories with spaces in them.

How to run 'cd' in shell script and stay there after script finishes?

I used 'change directory' in my shell script (bash)
#!/bin/bash
alias mycd='cd some_place'
mycd
pwd
pwd prints some_place correctly, but after the script finished my current working directory doesn't change.
Is it possible to change my path by script?
You need to source the file as:
. myfile.sh
or
source myfile.sh
Without sourcing the changes will happen in the sub-shell and not in the parent shell which is invoking the script. But when you source a file the lines in the file are executed as if they were typed at the command line.
While sourcing the script you want to run is one solution, you should be aware that this script then can directly modify the environment of your current shell. Also it is not possible to pass arguments anymore.
Another way to do, is to implement your script as a function in bash.
function cdbm() {
cd whereever_you_want_to_go
echo arguments to the functions were $1, $2, ...
}
This technique is used by autojump:
http://github.com/joelthelion/autojump/wiki
to provide you with learning shell directory bookmarks.
The script is run in a separate subshell. That subshell changes directory, not the shell you run it in. A possible solution is to source the script instead of running it:
# Bash
source yourscript.sh
# or POSIX sh
. yourscript.sh
It can be achieved by sourcing. Sourcing is basically execute the script in the same shell whereas normal execution(sh test.sh or ./test.sh) will create sub shell and execute script there.
test.sh
cd development/
ls
# Do whatever you want.
Execute test.sh by
source test.sh
. is shortest notation for source. So you can also do by
. test.sh
This will execute the script and change the directory of current shell to development/.
whenever you run a script on your login shell, a new subprocess is spawned and the script execution is done in a subshell.Once the script completes, the subshell exits and you are returned to the login shell.Hence whenever you do a cd through a script,the directory is changed to the path specified by cd, but by the time script finishes you come back to your login shell to the working directory from where you started the script.
The way to overcome this is use,
source yourscript.sh
what source does is it executes the script as TCL script, i.e it has the same effect as when you typed each line on the command line of your login shell and it executed from there. So this way when the script finishes after cd , it stays in that directory.
Another practical solution is to end your script by opening another shell session.
For instance:
#!/bin/bash
cd some_place
bash
This is useful, in my case, for scripts located in my ~/bin for instance, called from any other place. It is just a bit painful to type source ~/bin/mygoodoldscript instead of mygoo<TAB><ENTER>.
The downside is that the additional shell takes up a few more resources (not much).
Though there are answers. I think the intention of question is to use script to navigate to specific path.
Here is a simple practical solution works here without cancel out existing terminal environment flag.
provide a bash/tch/sh script to work for path generation
/* .goto.sh */
#!/usr/bin/env bash
echo '~/workspace'
add alias to the script output
alias goto 'cd `.goto.sh`'

Resources