- Calling one Bash script from another Script passing it arguments with quotes and spaces
- How to Call One Shell Script From Another
- 1. Introduction
- 2. Prerequisites
- 2.1. The Shebang
- 2.2. Make the File Executable
- 3. Run Script in a New Process
- 3.1. The bash Command
- 3.2. Call Script as a Normal Command
- 4. Run the Script in the Same Process
- 5. Conclusion
- How to run a shell script inside a shell script
- 3 Answers 3
Calling one Bash script from another Script passing it arguments with quotes and spaces
I’m actually trying to invoke a salt-stack command which is salt ‘*mysql’ cmd.run ‘bash /opt/clemson/mysql/bin/test_mysql_db_create «$1» «$2» «$3» «$4» «$5» «$6″‘ The double quotes don’t seem to work in this case. It worked when i had the single quotes for the most part but didn’t work in the case i specified in the question.
Are you saying that your real question is different from the one that you asked? 🙂 I have no idea what a «salt-stack» command is, but it looks like you may have a problem with multiple levels of quotes. You have $1 etc enclosed in double quotes, but the whole thing is inside single quotes — if salt-stack acts like bash, this means that you will get literal «$1» «$2» etc passed to your bash command. Perhaps you should ask a new question that is more specific to your actual situation.
My real question is different in the way that i constructed the above two test scripts showing what problem i had faced. Maybe i misinterpreted the problem. The problem is that i have made a script that executes a command in the form of salt ‘servername’ cmd.run ‘whatever command to execute’. whatever command to execute is what we write on the shell for example ./testscript. It has to be included in single quotes like this ‘./testscript’. How do i get this part to work: ‘./testscript $1 $2’ that is the command is enclosed in single quotes and the double quotes aren’t working inside that.
Yes, that is a different problem. You should ask a new question, with a snippet of code from your actual script. You can simplify the code that you post, but in this case you simplified it so much that it does not present the same problem that you are having.
You need to use : «$@» (WITH the quotes) or «$» (same, but also telling the shell where the variable name starts and ends).
(and do NOT use : $@ , or «$*» , or $* ).
#testscript1: echo "TestScript1 Arguments:" for an_arg in "$@" ; do echo "$" done echo "nb of args: $#" ./testscript2 "$@" #invokes testscript2 with the same arguments we received
I’m not sure I understood your other requirement ( you want to invoke ‘./testscript2’ in single quotes?) so here are 2 wild guesses (changing the last line above) :
'./testscript2' "$@" #only makes sense if "/path/to/testscript2" containes spaces? ./testscript2 '"some thing" "another"' "$var" "$var2" #3 args to testscript2
Please give me the exact thing you are trying to do
edit: after his comment saying he attempts tesscript1 «$1» «$2» «$3» «$4» «$5» «$6» to run : salt ‘remote host’ cmd.run ‘./testscript2 $1 $2 $3 $4 $5 $6’
You have many levels of intermediate: testscript1 on host 1, needs to run «salt», and give it a string launching «testscrit2» with arguments in quotes.
You could maybe «simplify» by having:
#testscript1 #we receive args, we generate a custom script simulating 'testscript2 "$@"' theargs="'$1'" shift for i in "$@" ; do theargs="$ '$i'" done salt 'remote host' cmd.run "./testscript2 $"
if THAt doesn’t work, then instead of running «testscript2 $», replace THE LAST LINE above by
echo "./testscript2 $" >/tmp/runtestscript2.$$ #generate custom script locally ($$ is current pid in bash/sh/. ) scp /tmp/runtestscript2.$$ user@remotehost:/tmp/runtestscript2.$$ #copy it to remotehost salt 'remotehost' cmd.run "./runtestscript2.$$" #the args are inside the custom script! ssh user@remotehost "rm /tmp/runtestscript2.$$" #delete the remote one rm /tmp/runtestscript2.$$ #and the local one
How to Call One Shell Script From Another
The Kubernetes ecosystem is huge and quite complex, so it’s easy to forget about costs when trying out all of the exciting tools.
To avoid overspending on your Kubernetes cluster, definitely have a look at the free K8s cost monitoring tool from the automation platform CAST AI. You can view your costs in real time, allocate them, calculate burn rates for projects, spot anomalies or spikes, and get insightful reports you can share with your team.
Connect your cluster and start monitoring your K8s costs right away:
1. Introduction
It’s common for developers to call one shell script from another. This could be for organizational purposes or to make a script more reusable. For example, if we have a script that deletes some unused files, we can call it from inside other scripts as a clean-up step to optimize disk space usage.
In this tutorial, we’ll see how we can call a script from inside another script and compare the pros and cons of the different ways we can do this.
2. Prerequisites
Before we get into the details of how to call our script, we need to do two things. The first is adding the shebang, and the second is making the file executable. In the next sections, we’ll see why we need to do this and how to do it.
2.1. The Shebang
The first thing we need to add to any script that we write is the shebang. We write it in the first line of our script, and it tells the kernel which program to use to run the script.
To write a shebang, we have to follow a specific format. We write “#!” followed by the path of the program that we want to use to run our script. So, for example, if we are writing a bash script, this will be our shebang:
Here /bin/bash is the path to the bash executable in most cases.
The shebang is not strictly necessary for the script to work. This is because the default behavior of the kernel is to use the same program that was used to launch the script to run that script. However, it’s really a best practice to add the shebang in order to avoid many errors that could come up later and to make our script more portable and robust.
2.2. Make the File Executable
Unlike the shebang, it’s mandatory to make the file executable so that we can call it from another script. To check whether the file is executable, we can run this in the terminal:
This command shows the details of the files present in the current directory.
As an example, we have created a directory containing two scripts (script1 and script2). Let’s run the previous command to see if our scripts are executable:
$ ls -l total 0 -rwxr-xr-x. 1 root root 0 Jan 27 15:26 script1 -rw-r--r--. 1 root root 0 Jan 27 15:26 script2
The key values important to us from the previous output are rw-r–r– and rwxr-xr-x, that are to the left of the file names. The r stands for read, w for write, and x for executable. Knowing that, we can see that script1 is executable while script2 is not.
We’ll use the chmod command to make script2 executable:
This adds the x to script2 and make it executable. Let’s check again to make sure it’s now executable:
$ ls -l total 0 -rwxr-xr-x. 1 root root 0 Jan 27 15:26 script1 -rwxr-xr-x. 1 root root 0 Jan 27 15:26 script2
As we can see, script2 is now executable, and we can now call it from script1.
3. Run Script in a New Process
When we call script2 from script1, there are two ways in which script2 can be executed.
The first one is that script2 is executed in a new separate process, and then the result is passed to script1 in its original process. The second way is that script2 is executed in the same original process as script1.
The advantage of the second way is that both scripts will have access to all the variables and functions defined in both of them. Also, this could lead to better performance as the system won’t need to create a new process to run the second script.
Let’s see the contents of the scripts that we’ll be using in this tutorial:
$ cat script1 #!/bin/bash echo "first script was called" x="1"
$ cat script2 #!/bin/bash echo "second script was called" echo $x
Next, we’ll see how to call script2 from script1.
3.1. The bash Command
The first command we’ll use is the bash command. This makes the kernel use the Bash program to run our script. Let’s add this line at the end of script1:
Now let’s call script1 to see the output:
$ ./script1 first script was called second script was called
At this point, we can see that we’re able to call script2 from inside script1 as we wanted.
However, the second script was not able to print the value of x. This is because it wasn’t able to see it as x was defined in the first script, and it was running in a separate process.
3.2. Call Script as a Normal Command
Now let’s replace the last line from script1 that contains “bash script2“, with the path to script2:
When we run script1, we’ll see this output:
$ ./script1 first script was called second script was called
We can see that the output is exactly the same as the previous command, which is what we expected.
When we call the script without choosing a certain shell to run it, it’s run using the program in the shebang. Since our shebang contains the Bash program, the kernel used it to run the script and produced the exact same output as the previous command where we explicitly choose to run our script using Bash.
4. Run the Script in the Same Process
If we want a script to have access to variables and functions defined in another script, we can use the source command.
The source command acts as if we copied the text from the script that was given to it as a parameter to the script in which it’s called.
Next, we will see an example that will help us better understand this.
In the last line of script1, let’s add the source command before the path to scipt2:
$ ./script1 first script was called second script was called 1
We can see that script2 was able to see the variable $x and print its value. This is because the source command acted as if we copied the text in script2 to script1 and then ran script1. Thus, all the code was running in the same process, and the script was able to print the variable successfully.
5. Conclusion
In this article, we discussed how to call a script from another script. This is a useful technique that we can use in many applications.
Additionally, we compared different ways to do this and understood the difference between them. Depending on the use case, some commands may be more suitable than others. So, in the end, it’s up to us to choose the command that will best satisfy our needs.
How to run a shell script inside a shell script
I am using bash on Mac OSX. I have a shell file named myshell.sh and I use it to do a lot of things. I have a entrance.sh file which contains:
# content of entrance.sh ./myshell.sh arg1 arg2 ./myshell.sh arg3 arg4
./entrance.sh: line 2: myshell.sh: command not found
@PM2Ring yes it’s the same. After switching to full paths instead of relative, it works. thanks to YoMismo
3 Answers 3
./myshell.sh means the script myshell.sh is found in the current directory. If you run this script from somewhere else, it won’t work. You could use full paths, but in this case, the only sensible solutions are:
- Adding the location of myshell.sh to your $PATH (in case, myshell.sh really is something that is supposed to be called from everywhere). So, add PATH=»$PATH»:/dir/of/myshell at the beginning of the outer script.
- Put myshell.sh somewhere so that it’s accessible from everywhere (just like all other executables on the system). That would be /usr/local/bin most likely. Use this only if this script is universally useful.
If the scripts rely on local files in their directory (and may even break down and do damage if called from elsewhere), then you should either leave it in the current form (this actually prevents you to call them from places you are not supposed to), or use cd inside the script to get to the proper location. Be careful, use absolute paths in shell scripts for cd , it is too easy to break stuff if something goes wrong and you go out .. and cd -ing further in fails, you could escape out of your directory and reign chaos all over the parent directories.
Mostly I’d recommend solution #1.