Linux: Run a binary in a script - linux

i want to run a program via script.
normally i type ./program in the shell and the program starts.
my script looks like this:
#!/bin/sh
cd /home/user/path_to_the_program/
sh program
it fails, i think the last line went wrong...
i know this is childish question but thx a lot!

If ./program works in the shell, why not use it in your script?
#!/bin/sh
cd /home/user/path_to_the_program/
./program
sh program launches sh to try and interpret program as a shell script. Most likely it's not a script but some other executable file, which is why it fails.

When you type
./program
The shell tries to execute the program according to how it determines the file needs to be executed. If it is a binary, it will attempt to execute the entry subroutine. If the shell detects it is a script, e.g through the use of
#!/bin/sh
or
#!/bin/awk
or more generally
#!/path/to/interpreter
the shell will pass the file (and any supplied arguments) as arguments to the supplied interpreter, which will then execute the script. If the interpreter given in the path does not exist, the shell will error, and if no interpreter line is found, the shell will assume the supplied script is to executed by itself.
A command
sh program
is equivalent to
./program
when the first line of program contains
#!/bin/sh
assuming that /bin/sh is the sh in your path (it could be /system/bin/sh, for example). Passing a binary to sh will cause sh to treat it as a shell script, which it is not, and binary is not interpretable shell (which is plain text). That is why you cannot use
sh program
in this context. It will also fail due to program being ruby, awk, sed, or anything else that is not a shell script.

You don't need the sh and looks like you don't have the path to the program in your $PATH.
Try this:
#!/bin/sh
cd /home/user/path_to_the_program/
./program

You don't need the "sh" here. Just put "program" on the last line by itself.

This should be enough:
/home/user/path_to_the_program/program
If that does not work, check the following:
executable bit
shebang line of the program (if it is a script)

Related

What is the difference between `./example.sh` and `sh example.sh`

I am trying to play with bash and arrays. But executing a sample script, I got an unexpected syntax error message: example.sh: 3: example.sh: Syntax error: "(" unexpected. And this is the script
#!/bin/bash
array=( one two three )
If I run the script with ./example.sh it works and no errors are displayed. But if I run sh example.sh I get the error message.
I thought that these two commands are the same:
sh example.sh
./example.sh
so ... what is the difference between the two?
When you launch it via ./example.sh then the command specified in the first line of the script is used to interpret the content. So your script executes in a bash, where such syntax is allowed for arrays.
When you launch it via sh example.sh then sh is the command that is used to interpret the content of the file. sh is the original Unix shell (aka Bourne shell) and this shell is a little more rude than bash (Bourne again shell). You don't have such arrays. Note that in sh the first line of your script is just interpreted as a comment.
by using sh example.sh
- you are specifying what shell interpreter to use for that script. Example being "bash example.sh" instead of "sh example.sh" etc etc.
Running scripts this way disregards the "shebang (#!/bin/bash)" that you have specified inside of the script. Since you wrote a bash script but are trying to run it as just "sh", this is why it is failing
by using ./example.sh,
- You are specifying to run the script from your current directory. This will attempt to run the script in whatever shell you are currently in unless a shebang is specified. Since you have a "shebang" specified to run the script in bash... this is why it is working.
array_name=(value1 ... valuen)
This is how to initializes an array in bash only. When you execute ./example.sh, the shebang line #!/bin/bash tells the system to use bash to execute.
However, when you execute sh example.sh, sh is used to execute. In many Unix systems (like Linux), sh is equivalent to bash. It seems sh is a different shell on your system.

Script execute script without executing permission

I have perl script which has no execute permission (only rw) when I try to run this script "./script.pl" I get "Permission denied" and it is clear for me. But when I run this script using "perl -e script.pl" it works and script is executed though its own permission.
Could somebody explain this strange behaviour?
When you run the command
perl script.pl
the perl executable is executed from the shell (with some of the exec() system calls). The file /usr/bin/perl will then need +x because every file that is executed with exec() needs that. Perl will run with the argument script.pl and perl is programmed to open a file that is given to it on the command line and process the content.
When you run the file in this way
./script.pl
the shell will run the file script.pl directly by using some of the exec() system calls and then script.pl is the file that will need +x.
In other words, if you want to run the file like ./script.pl, you need to
chmod +x script.pl
You will also need a "shebang" as first line of your script, telling which command you want to use to run it. It will look like this:
#!/usr/bin/perl
In the first case you are trying to execute the script.
In the second case (if we ignore the -e) you are trying to execute perl, and are telling it to run the code in the file script.pl.
(The -e causes it to try to run the literal text script.pl as Perl code)

How to run a csh script from a sh script

I was wondering if there is a way to source a csh script from a sh script. Below is an example of what is trying to be implemented:
script1.sh:
#!/bin/sh
source script2
script2:
#!/bin/csh -f
setenv TEST 1234
set path = /home/user/sandbox
When I run sh script1.sh, I get syntax errors generated from script2 (expected since we are using a different Shebang). Is there a way I can run script2 through script1?
Instead of source script2 run it as:
csh -f script2
Since your use case depends on retaining environment variables set by the csh script, try adding this to the beginning of script1:
#!/bin/sh
if [ "$csh_executed" -ne 1 ]; then
csh_executed=1 exec csh -c "source script2;
exec /bin/sh \"$0\" \"\$argv\"" "$#"
fi
# rest of script1
If the csh_executed variable is not set to 1 in the environment, run a csh script that sources script2 then executes an instance of sh, which will retain the changes to the environment made in script2. exec is used to avoid creating new processes for each shell instance, instead just "switching" from one shell to the next. Setting csh_executed in the environment of the csh command ensures that we don't get stuck in a loop when script1 is re-executed by the csh instance.
Unfortunately, there is one drawback that I don't think can be fixed, at least not with my limited knowledge of csh: the second invocation of script1 receives all the original arguments as a single string, rather than a sequence of distinct arguments.
You don't want source there; it runs the given script inside your existing shell, without spawning a subprocess. Obviously, your sh process can't run something like that which isn't a sh script.
Just call the script directly, assuming it is executable:
script2
The closest you can come to sourcing a script with a different executor than your original script is to use exec. exec will replace the running process space with the new process. Unlike source, however, when your exec-ed program ends, the entire process ends. So you can do this:
#!/bin/sh
exec /path/to/csh/script
but you can't do this:
#!/bin/sh
exec /path/to/csh/script
some-other-command
However, are you sure you really want to source the script? Maybe you just want to run it in a subprocess:
#!/bin/sh
csh -f /path/to/csh/script
some-other-command
You want the settings in your csh script to apply to the sh script that invokes it.
Basically, you can't do that, though there are some (rather ugly) ways you could make it work. If you execute your csh script, it will set those variables in the context of the process running the script; they'll vanish as soon as it returns to the caller.
Your best bet is simply to write a new version of your csh script as an sh script, and source or . it from the calling sh script.
You could translate your csh script:
#!/bin/csh -f
setenv TEST 1234
set path = /home/user/sandbox
to this:
export TEST=1234
export PATH=/home/user/sandbox
(csh treats the shell array variable $path specially, tying it to the environment variable $PATH. sh and its derivatives don't do that, they deal with $PATH itself directly.)
Note that a script intended to be sourced should not have a #! line at the top, since it doesn't make sense to execute it in its own process; you need to execute its contents in the context of the caller.
If maintaining two copies of the script, one to be sourced from csh or tcsh scripts and another to be sourced or .ed from sh/ksh/bash/zsh script, is not practical, there are other solutions. For example, your script can print a series of sh commands to be executed; you can then do something like
eval `./foo.csh`
(line endings will pose some issues here).
Or you can modify the csh script so it sets the required environment variables and then invokes some specified command, which could be a new interactive shell; this is inconvenient, since it doesn't set those variables in the interactive shell you're running.
If a software package requires some special environment variables to be set, it's common practice to provide scripts called, for example, setup.sh and setup.csh, so that sh/ksh/bash/zsh users can do:
. /path/to/package/setup.sh
and csh/tcsh users can do:
source /path/to/package/setup.csh
Incidentally, this command:
set path = /home/user/sandbox
in your sample script is probably not a good idea. It replaces your entire $PATH with just a single directory, which means you won't be able to execute simple commands like ls unless you specify their full paths. You'd usually want something like:
set path = ( $path /home/user/sandbox )
or, in sh:
PATH=$PATH:/home/user/sandbox

How to change Example.bat to Example.pl?

I have read other threads enter link description herethat discuss .bat to L/unix conversions, but none has been satisfactory. I have also tried a lot of hack type approach in writing my own scripts.
I have the following example.bat script that is representative of the kind of script I want to run on unix.
Code:
echo "Example.bat"
perl script1 param.in newParam.in
perl script2 newParam.in stuff.D2D stuff.D2C
program.exe stuff.D2C
perl script3 stuff.DIS results.out
My problem is I don't know how to handle the perl and program.exe in the unix bash shell. I have tried putting them in a system(), but that did not work. Can someone please help me?
Thank you!
Provided that you have an executable file named program.exe somewhere in your $PATH (which you well might — Unix executables don't have to end in .exe, but nothing says they can't), the code you've pasted is a valid shell script. If you save it in a file named, say, example.bat, you can run it by typing
sh example.bat
into the shell prompt.
Of course, Unix shell scripts are usually given the suffix .sh — or no suffix at all — rather than .bat. Also, if you want your script to be executable directly, by typing just
example.sh
rather than sh example.sh, you need to do three things:
Start the script with a "shebang" line: a line that begins with #! and the full path to the shell interpreter you want to use to run it (e.g. /bin/sh for the basic Bourne shell), like this:
#!/bin/sh
echo "This is a shell script."
# ... more commands here ...
Mark your script as executable using the chmod command, e.g.
chmod a+rx example.sh
Put your script somewhere along your $PATH. On Unix, the default path will not normally contain the current directory ., so you can't execute programs from the current directory just by typing their name. You can, however, run them by specifying an explicit path, e.g.
./example.sh # runs example.sh from the current directory
To find out what your $PATH is, just type echo $PATH into the shell.

Linux shell strange situation

Does anyone know why the following script works?
#a-random-junk-string
echo HI
The shell executes the echo command, and outputs HI. I thought that since there is no "!" after the "#", the shell would give an error.
If there is no #! specifying a specific interpreter, the kernel will not intercept and launch it with the specified program.
However, the current shell may still interpret it as a command file, which is what you are seeing take place.
When the shell is asked to run a file with the executable bit turned on then it will examine the file and determine if it begins with a shebang #! if it does then it will execute that command which will get it's program text from the remainder of the file.
If the file does not start with a shebang then the shell will attempt to execute it itself. This is what is happening for you and the shell interprets the first line as a comment.

Resources