Problem in running a script - bash

i have unix shell script which is need to be run like below
test_sh XYZ=KLMN
the content of the script is
#!/bin/ksh
echo $XYZ
for using the value of XYZ i have do set -k before i run the script.
is there a way where i can do this without doint set -k before running the script. or is there something that i can do in the script where i can use value of the parameter given while running the script in the below way
test_sh XYZ=KLMN
i am using ksh.
Any help is appreciated.

How about running this?
XYZ=KLMN ./test_sh //running from directory where test_sh is

If your script needs no other arguments, a quick and dirty way do to it is to put
eval "$#"
at the start of your script. This will evaluate the command line arguments as shell commands. If those commands are to assign a shell/environment variable, then that's what it will do.
It's quick-and-dirty since anything could be put on the command line, causing problems from a syntax error to a bad security hole (if the script is trusted).
I'm not sure if "$#" means the same in ksh as it does in bash - using just $* (without quotes) would work too, but is even dirtier.

It looks like you are trying to use the environment variable "INSTANCE" in your script.
For that, the environment variable must be set in advance of executing your script. Using the "set" command sets exportable environment variables. Incidentally, my version of ksh dates from 1993 and the "-k" option was obsolete back then.
To set an environment variable so that it is exported into spawned shells, simply use the "export" command like so:
export INSTANCE='whatever you want to put here'
If you want to use a positional parameter for your script -- that is have the "KLMN" value accessed within your script, and assuming it is the first parameter, then you do the following in your script:
#!/bin/ksh
echo $1
You can also assign the positional parameter to a local variable for later use in your script like so:
#!/bin/ksh
param_one=$1
echo $param_one
You can call this with:
test_sh KLMN
Note that the spacing in the assignment is important -- do not use spaces.

I am tring this option
#!/bin/ksh
echo $1
awk '{FS="=";print $2}' $1
and on the command line
test_sh INSTANCE=LSN_MUM
but awk is failing.is there any problem over here?

Probably #!/bin/ksh -k will work (untested).

Related

Is there a good way to preload or include a script prior to executing another script?

I am looking to execute a script but have it include another script before it executes. The problem is, the included script would be generated and the executed script would be unmodifiable. One solution I came up with, was to actually reverse the include, by having the include script as a wrapper, calling set to set the arguments for the executed script and then dotting/sourcing it. E.g.
#!/bin/bash
# Generated wrapper or include script.
: Performing some setup...
target_script=$1 ; shift
set -- "$#"
. "$target_script"
Where target_script is the script I actually want to run, importing settings from the wrapper.
However, the potential problem I face is that callers of the target script or even the target script itself may be expecting $0 to be set to the path of it's location on the file system. But because this wrapper approach overrides $0, the value of $0 may be unexpected and could produce undefined behaviour.
Is there another way to perform what is in effect, an LD_PRELOAD but in the scripted form, through bash without interfering with its runtime parameters?
I have looked at --init-file or --rcfile, but these only seem to be included for interactive shells.
Forcing interactive mode does seem to allow me to specify --rcfile:
$ bash --rcfile /tmp/x-include.sh -i /tmp/xx.sh
include_script: $0=bash, $BASH_SOURCE=/tmp/x-include.sh
target_script: $0=/tmp/xx.sh, $BASH_SOURCE=/tmp/xx.sh
Content of the x-include.sh script:
#!/bin/bash
echo "include_script: \$0=$0, \$BASH_SOURCE=$BASH_SOURCE"
Content of the xx.sh script:
#!/bin/bash
echo "target_script: \$0=$0, \$BASH_SOURCE=$BASH_SOURCE"
From the bash documentation:
When bash is started non-interactively, to run a shell script, for example, it looks for the variable BASH_ENV in
the environment, expands its value if it appears there, and uses the expanded value as the name of a file to read
and execute. Bash behaves as if the following command were executed:
if [ -n "$BASH_ENV" ]; then . "$BASH_ENV"; fi
but the value of the PATH variable is not used to search for the file name.
So that settles it then:
BASH_ENV=/tmp/x-include.sh /bin/bash /tmp/xx.sh

Concatenate command string in a shell script

I am maintaining an existing shell script which assigns a command to a variable in side a shell script like:
MY_COMMAND="/bin/command -dosomething"
and then later on down the line it passes an "argument" to $MY_COMMAND by doing this :
MY_ARGUMENT="fubar"
$MY_COMMAND $MY_ARGUMENT
The idea being that $MY_COMMAND is supposed to execute with $MY_ARGUMENT appended.
Now, I am not an expert in shell scripts, but from what I can tell, $MY_COMMAND does not execute with $MY_ARGUMENT as an argument. However, if I do:
MY_ARGUMENT="itworks"
MY_COMMAND="/bin/command -dosomething $MY_ARGUMENT"
It works just fine.
Is it valid syntax to call $MY_COMMAND $MY_ARGUMENT so it executes a shell command inside a shell script with MY_ARGUMENT as the argument?
With Bash you could use arrays:
MY_COMMAND=("/bin/command" "-dosomething") ## Quoting is not necessary sometimes. Just a demo.
MY_ARGUMENTS=("fubar") ## You can add more.
"${MY_COMMAND[#]}" "${MY_ARGUMENTS[#]}" ## Execute.
It works just the way you expect it to work, but fubar is going to be the second argument ( $2 ) and not $1.
So if you echo arguments in your /bin/command you will get something like this:
echo "$1" # prints '-dosomething'
echo "$2" # prints 'fubar'

Bash command line arguments, replacing defaults for variables

I have a script which has several input files, generally these are defaults stored in a standard place and called by the script.
However, sometimes it is necessary to run it with changed inputs.
In the script I currently have, say, three variables, $A $B, and $C. Now I want to run it with a non default $B, and tomorrow I may want to run it with a non default $A and $B.
I have had a look around at how to parse command line arguments:
How do I parse command line arguments in Bash?
How do I deal with having some set by command line arguments some of the time?
I don't have enough reputation points to answer my own question. However, I have a solution:
Override a variable in a Bash script from the command line
#!/bin/bash
a=input1
b=input2
c=input3
while getopts "a:b:c:" flag
do
case $flag in
a) a=$OPTARG;;
b) b=$OPTARG;;
c) c=$OPTARG;;
esac
done
You can do it the following way. See Shell Parameter Expansion on the Bash man page.
#! /bin/bash
value=${1:-the default value}
echo value=$value
On the command line:
$ ./myscript.sh
value=the default value
$ ./myscript.sh foobar
value=foobar
Instead of using command line arguments to overwrite default values, you can also set the variables outside of the script. For example, the following script can be invoked with foo=54 /tmp/foobar or bar=/var/tmp /tmp/foobar:
#! /bin/bash
: ${foo:=42}
: ${bar:=/tmp}
echo "foo=$foo bar=$bar"

passing command line arguments to a shell script doesn't work

I want to write a script that will change to different directories depending on my input. something like this:
test.sh:
#!/bin/bash
ssh machine001 '(chdir ~/dev$1; pwd)'
But as I run ./test.sh 2 it still goes to ~/dev. It seems that my argument gets ignored. Am I doing anything very stupid here?
Bash ignores any variable syntax inside the single-quoted(') strings. You need double quotes(") in order to make a substitution:
#!/bin/bash
ssh machine001 "(chdir ~/dev$1; pwd)"
The parameter is enclosed in single quotes, so it isn't expanded on the local side. Use double-quotes instead.
#!/bin/bash
ssh machine001 "chdir ~/dev$1; pwd"
There's no need for the (...), since you are only running the pair of commands then exiting.

Bash script doesn't set variable when run from script, but works fine from prompt

Why does the following work from the prompt but fail when stuck inside a bash script? The bash script produces one empty line leading me to believe the variable isn't being set:
echo "red sox" | read my_var
echo $my_var
UPDATE: Since I guess my example isn't working, what I'm really trying to do is take I/O and pipe it into a variable to so I can do things with it. How do I do this? I thought this should be taken care of by the read command, but maybe there's another way?
If you are asking this because you simplified from a more general problem such as:
someprog args | read my_var
you should be using command substitution:
my_var=$(someprog args)
The reason read doesn't work in a pipe the way you have it is that it creates a subshell. Variables set in a subshell don't persist to their parents. See BashFAQ/024.
You can store the output of a command in a variable using either backticks or $() syntax:
my_var=`cat /some/file.txt`
Now the content of /some/file.txt is stored in $my_var. Same thing, with different syntax:
my_var=$(cat /some/file.txt)
It doesn't work at the prompt. My guess is you already have my_var set in your CLI, and are just retrieving that at the prompt.
Try this:
$ my_var="nothing"; echo "red sox" | read my_var; echo $my_var
If you want the my_var variable to have a constant value, as in your question, why not just do:
my_var="red sox"
What are you trying to do? Please explain what you wan't to do first.
If you're trying to set a variable this is what you need:
my_var="red sox"
echo $my_var
If you need it globally you should set it in env:
export my_var

Resources