I am passing variable from one shell script to another which is being executed on another remote server.
Script 1
echo "Identification No."
read id
export id
ssh atul#10.95.276.286 'bash -s' < data_file.sh
Script 2
echo "ID is ---- "$id
cd /abc/xyz/data/
cat data_abcxyz.txt|grep '|$id|'|wc -l
By this way I am not able to get any output even the id is also null in the second script.
I have also tried
ssh atul#10.95.276.286 'bash -s' < data_file.sh "$id"
But got no output.
Any help on this is greatly appreciated. I am using unix AIX.
export on one host is absolutely not going to affect an entirely different host... it doesn't even affect another shell running on the current host.
Your second attempt is better and might even work if your script were checking for positional arguments but it isn't. (It might not even work in that case as I'm not at all sure that the command line argument would make it through to the script through ssh and bash -s.
You might be able to do something more like:
ssh atul#10.95.276.286 "bash -s $id" < data_file.sh
to pass the argument to the remote bash directly but your script would still need to use positional arguments and not expecting named variables to already exist.
Exporting won't have any effects on the environment of remote scripts.
You can set up a remote script's environment by specifying the env variables on the command line before the actual command, which you can btw use for local commands too.
ssh atul#10.95.276.286 "id=$id bash -s" < data_file.sh
If you pass "$id" this way:
ssh atul#10.95.276.286 'bash -s' < data_file.sh "$id"
It'll be your script's first parameter, AKA "$1" and you'll be able to access it from your script that way.
Note that '|$id|' in your "Script 2" will be interpreted as a literal string, since you're using single quotes.
Related
I want to log into server based on user's choice so I wrote bash script. I am totally newbie - it is my first bash script:
#!/bin/bash
echo -e "Where to log?\n 1. Server A\n 2. Server B"
read to_log
if [ $to_log -eq 1 ] ; then
echo `ssh user#ip -p 33`
fi
After executing this script I am able to put a password but after nothing happens.
If someone could help me solve this problem, I would be grateful.
Thank you.
The problem with this script is the contents of the if statement. Replace:
echo `ssh user#ip -p 33`
with
ssh user#ip
and you should be good. Here is why:
Firstly, the use of back ticks is called "command substitution". Back ticks have been deprecated in favor of $().
Command substitution tells the shell to create a sub-shell, execute the enclosed command, and capture the output for assignment/use elsewhere in the script. For example:
name=$(whoami)
will run the command whoami, and assign the output to the variable name.
the enclosed command has to run to completion before the assignment can take place, and during that time the shell is capturing the output, so nothing will display on the screen.
In your script, the echo command will not display anything until the ssh command has completed (i.e. the sub-shell has exited), which never happens because the user does not know what is happening.
You have no need to capture the output of the ssh command, so there is no need to use command substitution. Just run the command as you would any other command in the script.
I have a bash script that needs to connect to another server for parts of it's execution. I have tried many of the standard instructions and syntaxes for executing ssh commands, but with little progress.
On the remote server, I need to source a shell script that contains several env parameters for some software. One of these parameters are then used in a filepath to point to an executable, which contains a function ' -lprojects ' that can list the projects for the software on that server.
I have verified that running the commands on the server itself works multiple times. My issue is when I try to run the same commands over SSH. If I use the approach where I use the env variable for the filepath, it shows that the variable is null in the filepath, giving a file/directory not found error. If I hard-code the filepath to point to the executable, it gives me an error saying that the shell script is not sourced (which I assume it needs for other functions and apis for the executable to reveal it's -lprojects function)
Here is how the code looks like somewhat:
ssh remote.server 'source /filepath/remotescript.sh'
filelist=$(ssh remote.server $REMOTEVARIABLE'/bin/executable -lprojects')
echo ${filelist[#]}
for file in $filelist
do
echo $file
ssh SERVER2 awk 'something' /filepath/"$file"/somefile.txt | sed 'something' >> filepath/values.csv;
done
As you can see, I then also need to loop through the contents of the -lprojects output in the remote.server, do some awk and sed on the files to extract the wanted text (this works), but then I need to write that back to the client (local server) values.csv file. This is more generic, as there will be several servers I have to do this for, but all of them have to write to the same .csv file. For simplicity, you can just regard this as a one remote server case, since it is vital I get it working for at least one now in the beginning.
Note that I also tried something like:
ssh remote.server << EOF
'source /filepath/remotescript.sh'
filelist=$(ssh remote.server $REMOTEVARIABLE'/bin/executable -lprojects')
EOF
But with similar results. Also placing the single-quotes in the filelist both before and after the remotevariable, etc.
How do I go about properly doing this?
To access the environment variable, you must source the script that defines the environment within the same SSH call as the one where you are using it, otherwise, you're running your commands in two different shells which are unrelated:
filelist=$(ssh remote.server 'source /filepath/remotescript.sh; $REMOTEVARIABLE/bin/executable -lprojects')
Assuming executable outputs one file name per line, you can use readarray to achieve the effect :
readarray -t filelist < <(ssh remote.server '
source /filepath/remotescript.sh
$REMOTEVARIABLE/bin/executable -lprojects
'
)
echo ${filelist[#]}
for file in $filelist
do
echo $file
ssh SERVER2 awk 'something' /filepath/"$file"/somefile.txt | sed 'something' >> filepath/values.csv;
done
I'm writing a script that would give me an ability to execute other local bash scripts remotely over SSH without uploading them. Some of my servers have Linux, some FreeBSD with csh as default. So far, I've came to the following:
ssh remote_server 'bash -c '\'"$(cat local_script.sh)"\'' script_parameters'
This allows me to execute local_script.sh on remote_server, supports interactivity (for example, "read" command will work in local_script.sh), and I can transfer positional parameters to the script. The problem is that if a local_script.sh has multiple lines the code above works for remote servers with bash default shell only. On FreeBSD sshd starts csh first to execute "bash -c" command and tries to pass the script code (the result of $(cat local_script.sh)) to it as the first parameter. But because this code is multiline and csh wants the closing quote be on the same line as the opening quote I get the "Unmatched '." error. So csh just can't parse this escaped multiline parameter to pass it to the bash process.
The only solution I can see now is to parse the local_script.sh and automatically rewrite it into a one-liner using ";" delimiters before passing it via SSH. But this requires creating another script and seems to be not so easy. So I'd like to ask if this csh miltiline parsing problem can be resolved somehow?
What about using standard input /dev/stdin ?
ssh remote_server bash /dev/stdin script_parameters < local_script.sh
Using two different commands and temporary file
bash
ssh remote_server $'tmp=`mktemp tmp.XXXXXX`;cat <<\'HEREDOC_END\' >"$tmp"
'"$(cat local_script.sh)"'
HEREDOC_END
bash "$tmp" script_parameters ;rm "$tmp"'
csh
ssh remote_server 'set tmp=`mktemp tmp.XXXXXX`;cat <<"HEREDOC_END" >"$tmp"
'"$(cat local_script.sh)"'
"HEREDOC_END"
bash "$tmp" script_parameters ;rm "$tmp"'
In this particular case, there is no need to keep the outermost quotes.
ssh remote_server bash -c "\"$(cat local_script.sh)\"" script_parameters
This is not entirely robust; for example, single quotes in local_script.sh will not quote text verbatim. So the following example
echo 'fnord "$(echo yes)"'
will have the command substitution evaluated remotely even though the string is in single quotes. In the general case, you'd have to replace cat with, basically, a shell parser which identifies constructs which need escaping.
I have a problem with an execution of a shell script into a remote shell.
I can't get value of $ARQ_END.
ssh -T user#MACHINE << 'EOSSH'
/app/work/leo/ReturnFileName.sh #This script returns a filename like: ADDRESS_BR_RECIFE_20170913.txt
ARQ_END="`/app/work/leo/ReturnFileName.sh`"
EOSSH
echo $ARQ_END #Returns nothing! Expected to return: ADDRESS_BR_RECIFE_20170913.txt
Setting a variable in a subshell isn't visible in the parent shell. You need to set the variable directly in the parent shell. The way to do that is to pass the output of ReturnFileName.sh up through the ssh session and to the parent shell and capture it there.
ARQ_END=$(ssh user#MACHINE /app/work/leo/ReturnFileName.sh)
echo "$ARQ_END"
Thanks, it works!
I used the case as you posted:
ARQ_END=$(ssh user#MACHINE /app/work/leo/ReturnFileName.sh)
echo "$ARQ_END"
In one of my bash script I want to read and use the variable value from other script which is on remote machine.
How should I go ahead to resolve this. Any related info would be helpful.
Thanks in advance!
How about this (which is code I cannot currently test myself):
text=$(ssh yourname#yourmachine 'grep uploadRate= /root/yourscript')
It assumes that the value of the variable is contained in one line. The variable text now contains you variable assignment, presumably something like
uploadRate=1MB/s
There are several ways to convert the text/code into a real variable assignment in your current script, like evaluating the string or using grep. I would recommend
uploadRate=${text#*=}
to just remove the part up and including the =.
Edit: One more caveat to mention is that this only works if the original assignment does not contain variable references itself like in
uploadRate=1000*${kB}/s
ssh user#machine 'command'
will print the standard output of the remote command.
I would tell two ways at least:
1) You can simply redirect output to a file from remote server to your system with scp command...It would work for you.Then your script on your machine should read that file as an argument...
script on your machine:
read -t 50 -p "Waiting for argumet: " $1
It waits for output from remote machine,
Then you can
sshpass -p<password> scp user#host:/Path/to/file /path/to/script/
What you need to do:
You should tell the script from your machine, that the output from scp command is the argument($1)
2)Run script from your machine:
#!/bin/bash
script='
#Your commands
'
sshpass -p<password> ssh user#host $script
And you have also another ways to run script to do sth with remote machine.