Issue
I need to save in a variable on my local machine a value that is returned from a script or command - let's take bash /tmp/script1.sh
for the example - which lies on a remote machine - let's say machine_C, at path /tmp/script1.sh and contains:
#! bin/bash
echo "Hello! I am speaking from remote machine: $(hostname -I)"
However, this machine can only be reached via ssh by passing through more than one bridge machine, in my case two - let's say machine_P and machine_C.
Furthermore, because of access lock, only a particular user - let's say user_O - present on machine_B, can access the next machines, so when my code reach machine_B, it needs to switch to user_O.
Note: I cannot ssh in machine_B directly as user_O because of access lock. Also, I want add a timeout to my ssh command, so that if the access fails, the process does not remain struck forever.
So the procedure is
- access machine_B as user_B,
- from that machine, switch to user_O and access machine_P as user_O,
- From that machine, access machine_C as user O,
- in machine_C, run the commmand
bash /tmp/script1.sh
How can I do it?
Solution
Short answer:
ssh_timeout=3
ip_string=$(ssh -o ConnectTimeout=$ssh_timeout $user_B@$remote_machine_B_ip \
"sudo -i -u user_O ssh -o ConnectTimeout=$ssh_timeout $user_O@$remote_machine_P_ip \
\"ssh -o ConnectTimeout=$ssh_timeout $user_O@$remote_machine_C_ip \
\"bash /tmp/script1.sh\" \
\" \
" \
)
Explanation:
First, we need a variable where to store the value returned from script1.sh, so we start by:
info=...
then we need to run a command that will in the end run the script on machine_C to get that value:
info=$(...)
then we do the first ssh into machine_B as user_O, with timeout option (-o ConnectTimeout=seconds
),
and the command that we want to be run by ssh must be put between delimiters; we choose double quotes ("
):
info=$(ssh -o ConnectTimeout=$ssh_timeout $user_B@$remote_machine_B_ip "...")
then user_B on machine_B must switch to user_O and then do a ssh into machine_P and run another command there.
That command must be enclosed in delimiters, and since we already used double quotes ("
),
in order to avoid that the code reads this second couples of quotes as closure of the first ones,
we must escape them with \
, so that they will be read as quotes only when the code run as machine_P:
info=$(ssh -o ConnectTimeout=$ssh_timeout $user_B@$remote_machine_B_ip "sudo -i -u user_O ssh -o ConnectTimeout=$ssh_timeout $user_O@$remote_machine_P_ip \"...\" ")
let's put this command in a more understandable form by displaying it into multiple lines.
In order to prevent the code to stop reading the command as we break the line, we must escape the new line with \
info=$(ssh -o ConnectTimeout=$ssh_timeout $user_B@$remote_machine_B_ip \
"sudo -i -u user_O ssh -o ConnectTimeout=$ssh_timeout $user_O@$remote_machine_P_ip \"...\" " \
)
then user_O on machine_P must do a ssh into machine_C and run a command.
That command must be enclosed in delimiters, and again, since we already used double quotes ("
),
in order to avoid that the code reads this third couples of quotes as closure of the first ones,
we must escape them.
And again, let's put the command on multiple lines:
info=$(ssh -o ConnectTimeout=$ssh_timeout $user_B@$remote_machine_B_ip \
"sudo -i -u user_O ssh -o ConnectTimeout=$ssh_timeout $user_O@$remote_machine_P_ip \
\"ssh -o ConnectTimeout=$ssh_timeout $user_O@$remote_machine_C_ip \"...\" \" \
" \
)
In the very end, we have to put the command we want to be run on machine_C in the \"...\"
slot we prepared before.
The syntax of this command is exactly the same as the one we would use to write and run this command on our local machine, if the same script were at the indicated location.
# define ssh_timeout
ssh_timeout=3
info=$(ssh -o ConnectTimeout=$ssh_timeout $user_B@$remote_machine_B_ip \
"sudo -i -u user_O ssh -o ConnectTimeout=$ssh_timeout $user_O@$remote_machine_P_ip \
\"ssh -o ConnectTimeout=$ssh_timeout $user_O@$remote_machine_C_ip \
\"bash /tmp/script1.sh\" \
\" \
" \
)
echo "$info"
and the output is
I am speaking from remote machine: <remote_machine_C_ip>
Answered By - Tms91 Answer Checked By - Pedro (WPSolving Volunteer)