I have to implement a scenario where I need to login as root and then perform some ssh and scp commands through python to automate certain workflows.
Example: Suppose MACHINE12 is my host and current user is test, i.e test#MACHINE12
I want a interactive code to be written in such a way that , if I put the following commands it should login as root user and the session should be maintained to perform other operations in python.
{test#MACHINE12} su
password:
once password is entered, logged in as root.
{test#MACHINE12 test}
Perform other commands here
{test#MACHINE12 test} ssh user1#abc
I tried this using the pexpect command in python, but the root session is not maintained or staying to perform other operations.
The commands can be only executed if the logged in session is root because abc host need root permission.
Find my tried snippet here:
def loginAsroot():
childTab = pexpect.spawn("su") //command su to enter to root
childTab.expect(":")
childTab.sendline("asdgfgh") // entering password
childTab.expect("#")
def runCommands():
command = "ssh user1#abc 'cat /dfg/hello.txt'>> /doc/g/auth.txt"
process = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
output, error = process.communicate(timeout=10000)
return output
//function call
loginAsroot()
runCommands()
I'am trying to do linux command execution it is giving permission denied error, because the root session is not staying, its getting logged out. Hence Permission denied
How can I achieve this kind of executions?
You're trying to use both pexpect and subprocess. These are possibly spawning different sessions. Does the following work?
import pexpect
child = pexpect.spawn('su')
child.expect(':')
child.sendline('asdgfgh')
child.expect('#')
command = "ssh user1#abc 'cat /dfg/hello.txt'>> /doc/g/auth.txt"
child.sendline(command)
child.expect('#')
I think using either of the modules throughout would solve your issue.
For SSH, I like Paramiko, because it takes care of overhead. To demonstrate, I wrote two versions of the code: one using Pexpect all the way, and the other using Paramiko. Just remember:
Make sure the IP address of the remote machine is not in the /root/.ssh/known_hosts; otherwise you get the WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! error.
I prefer expect_exact because expect uses regex patterns. With expect, you can get an error if you look for a prompts that use regex characters, such as $.
I also prefer using su - over su if I have to use root, since it clears the environment variables.
Thanks for the question, by the way. Sometimes I forget what I just told you to remember :facepalm: !
NOTE - Tested using two Debian VM's and Python 3.9. I changed the prompts and obscured the passwords and IP addresses.
Using Pexpect (with everything echoed to STDOUT):
import sys
import pexpect
child = pexpect.spawn("su -", logfile=sys.stdout.buffer)
child.expect_exact("Password:")
child.sendline("**********")
child.expect_exact("#")
child.sendline("ssh user#192.168.X.X")
while True:
# Must use expect_exact to avoid expect regex conflict with prompt ($)!
index = child.expect_exact(
["Are you sure you want to continue connecting", "password:", "$", ])
if index == 0:
child.sendline("yes")
elif index == 1:
child.sendline("**********")
else:
break
child.sendline("cat hello.txt >> auth.txt")
child.expect_exact("$")
child.sendline("cat auth.txt")
child.expect_exact("$")
# If you do not use the logfile, you can make sure the file got copied using:
# print(child.before)
child.sendline("exit")
child.expect_exact("#")
child.sendline("exit")
# The child closes after the exit command (EOF); this is just to make sure
child.expect_exact(["$", pexpect.EOF, ])
child.close()
print("Script complete. Have a nice day.")
Output:
Password: **********
test#MACHINE12:~# ssh user1#192.168.X.X
ssh user1#192.168.X.X
The authenticity of host '192.168.X.X (192.168.X.X)' can't be established.
RSA key fingerprint is SHA256:********************************************
This key is not known by any other names
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
yes
Warning: Permanently added '192.168.X.X' (RSA) to the list of known hosts.
**********#192.168.X.X's password: **********
Last login: Sat Dec 4 20:40:12 2021 from 192.168.X.X
user1#192.168.X.X:~$ cat hello.txt >> auth.txt
cat hello.txt >> auth.txt
user1#192.168.X.X:~$ cat auth.txt
cat auth.txt
Hello, world!
user1#192.168.X.X:~$ b' cat auth.txt\r\nHello, world!\r\nuser1#192.168.X.X:~'
exit
exit
logout
Connection to 192.168.X.X closed.
test#MACHINE12:~# exit
exit
Script complete. Have a nice day.
Process finished with exit code 0
Using Paramiko (without echoing):
import paramiko
import pexpect
child = pexpect.spawn("su -")
child.expect_exact("Password:")
child.sendline("**********")
child.expect_exact("#")
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect("192.168.X.X", username="user1", password="**********")
ssh.exec_command("cat hello.txt >> auth.txt")
_, chan_out, _ = ssh.exec_command("cat auth.txt")
print("\nauth contents:", chan_out.read().decode())
ssh.close()
child.sendline("exit")
child.expect_exact(["$", pexpect.EOF, ])
child.close()
print("Script complete. Have a nice day.")
Output:
auth contents: Hello, world!
Good luck with your code!
Related
Once after connecting to the unix server with my id credentials, I am trying to login as sudo user by providing sudo command and password. I tried different ways, but I am not successful. Below is my code
import paramiko
import time
#define SSH
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(policy=paramiko.AutoAddPolicy)
#Connect to ther server
ssh.connect('server',22,username='username',password='password')
transport = ssh.get_transport()
#create a channel
chan = transport.open_session()
#interactive shell
chan.get_pty()
chan.invoke_shell()
print(chan.recv(2000))
#execute command
chan.exec_command('sudo S su - test server')
chan.send('password')
chan.send('\n')
chan.exec_command('whoami')
print(chan.recv(2000))
chan.close()
is there any other way to provide the sudo commanfd and password
I've always used paramiko shell to do such things. It would basically mean treating it like 'expect' where it checks for a prompt based on some regex pattern to see the completion of a command. Based on the response from the command output or the prompt, you can send the subsequent command.
Here's a more complete overview:
https://github.com/fgimian/paramiko-expect
o's!
Maybe you can help me with this. I can't find an answer to my specific questions, because there is an obvious solution which I'm not allowed to use. But first things first, the context:
In my company, which is a service provider, we administrate a bunch of
Linux servers. Some of my colleagues has for a long time been running
a BASH script from a source server, that then performs some tasks over
SSH on a number of remote Linux servers. The tasks it performs has to
be executed as root, so what the script does is it authorizes the
source server as root on the remote Linux servers via SSH (the remote
servers has the source servers public SSH key). Then what happened is
a new security policy was enforced and now root login over SSH is
denied. So the mentioned method no longer works.
The solution I keep finding, which we are by policy not allowed to do, is to create an entry in the sudoers file allowing sudo to root without password for the specific user.
This is the terms and they have to obey that. The only procedure that is allowed is to log on to the target server with your personal user, and then sudo su - to root WITH password.
Cocky as I apparently was, I said, "It should be possible to have the script do that automatically", and the management was like "Cool, you do it then!" and now I'm here at Stack Overflow,
because I know this is where bright minds are.
So this is exactly what I want to do with a BASH script, and I do not know if it's possible or how it's done, I really hope you can help me out:
Imagine Bob, he's logged into the source server, and he wants to
execute the script against a target server. Knowing that root over SSH
doesn't work, the authorization part of the script has been upgraded.
When Bob runs the script, it prompts him for his password. The
password is then stored in a variable (encrypted would be amazing) and
the script then logs on the target server as his user (which is
allowed) and then automatically elevates him to root on the target
server using the password he entered on the source server. Now the
script is root and it runs its tasks as usual.
Can it be done with BASH? and how?
UPDATE:
The Script:
## define code to be run on the remote system
remote_script='sudo -S hostname'
## local system
# on the local machine: prompt the user for the password
read -r -p "Enter password for $host: " password
# ...and write the password, followed by a NUL delimiter, to stdin of ssh
ssh -t 10.0.1.40 "$remote_script" < <(printf '%s\0' "$password")
The error:
[worker#source ~]$ sh elevate.sh
Enter password for : abc123
elevate.sh: line 10: syntax error near unexpected token `<'
elevate.sh: line 10: `ssh -t 10.0.1.40 "$remote_script" < <(printf '%s\0' "$password")'
First: Because it exposes plaintext passwords to the remote system (where they can be read by an attacker using diagnostic tools such as strace or sysdig), this is less secure than correctly using the NOPASSWD: flag in sudoers. If your security team aren't absolute idiots, they'll approve a policy exemption (perhaps with some appropriate controls, such as having a dedicated account with access to a setuid binary specific to the command being run, with authentication to that account being performed via public key authentication w/ the private key stored encrypted) rather than approving use of this hack.
Second: Here's your hack.
## define code to be run on the remote system
remote_script='sudo -S remote_command_here'
## local system
# on the local machine: prompt the user for the password
read -r -p "Enter password for $host: " password
# ...and write the password, followed by a NUL delimiter, to stdin of ssh
ssh "$host" "$remote_script" < <(printf '%s\0' "$password")
Allright, this is not the final answer, but I think I'm getting close, with the great help of CharlesDuffy.
So far I can run the script without errors on a remote server, that already has the publickey of my source server. However the command I execute doesn't create a file as I tell it to on the remote system.
However the script seems to run and the password seems to be accepted by the remote system.
Also I have to change in the sudoers on the remote host the line "Defaults requiretty" to "Defaults !requiretty", else it will tell me that I need a TTY to run sudo.
#!/bin/bash
## define code to be run on the remote system
remote_script='sudo -S touch /elevatedfile'
## local system
# on the local machine: prompt the user for the password
read -r -p "Enter password for $host: " password
# ...and write the password, followed by a NUL delimiter, to stdin of ssh
ssh -T 10.0.1.40 "$remote_script" < <(printf '%s\0' "$password")
UPDATE: When I tail /var/log/secure on the remote host I get the following after executing the script, which seems like the password is not being accepted.
May 11 20:15:20 target sudo: pam_unix(sudo:auth): conversation failed
May 11 20:15:20 target sudo: pam_unix(sudo:auth): auth could not identify password for [worker]
May 11 20:15:20 target sshd[3634]: Received disconnect from 10.0.1.39: 11: disconnected by user
May 11 20:15:20 target sshd[3631]: pam_unix(sshd:session): session closed for user worker
What I see on the source server, from where I launch the script:
[worker#source ~]$ bash elevate.sh
Enter password for : abc123
[sudo] password for worker:
[worker#source ~]$
Just make a daemon or cron script running as root, that in turn will check for any new scripts in specified secure location (ie. DB that it only has READ access to), and if they exist, it will download and execute them.
I am having some issues trying to connect through telnet to a mail server.The main problem that I am having is that I need to create a script that logs me to the destination and I can't find a way to echo the password.
What I tried:
telnet host -l username ; echo 'password'
And still it asks for my password.Is there any way to fix this or I am doing something wrong?
First of all, you can use eval:
eval "{ echo user_name; sleep 1; echo pass; sleep 1; echo '?'; sleep 5; }" | telnet host_address
Make sure to replace user_name, pass, ? which is the command you want to run and host_address where your telnet host is listening; for me it is a local IP.
It’s surprisingly easy to script a set of command and pipe them into the telnet application. All you need to do is something like this:
(echo commandname;echo anothercommand) | telnet host_address
The only problem is the nagging login that you have to get through… it doesn’t show up right away. So if you pipe in an “echo admin” and then “echo password,” it will happen too quickly and won’t be sent to the server. The solution? Use the sleep command!
Adding in a couple of sleep 3 commands, to wait three seconds, solves the problem. First we’ll echo the username and password, and then we’ll echo the reboot command, and each time we’ll wait three seconds between. The final command will reboot the server immediately:
(sleep 3;echo admin;sleep 3;echo mypassword;sleep 3;echo system reboot;sleep 3;) | telnet host_address
You can put this into a shell script and run it whenever you want. Or you can add it to your cron like this (on OS X or Linux):
crontab -e
Add this line somewhere:
1 7 * * * (sleep 3;echo admin;sleep 3;echo mypassword;sleep 3;echo system reboot;sleep 3;) | telnet host_address
This will reboot your router at 7:01 AM each morning.
AFAIK, you won't be able to automate telnet that way. But it is still possible - even if it is a very bad idea (I'll elaborate on that later).
First why does your try fail :
you launched a telnet command reading from stdin (I suppose terminal) and writing to stdout and stderr (I suppose also a terminal)
if your telnet is reasonably recent, it tries to protect your authentication and asks your password from /dev/tty (for security reasons)
when that command has ended you write password on your own terminal
What should you do instead :
launch telnet with automatic authentication disable (on mine it is telnet -X SRA)
feed its input with the commands you want to pass
wait some delay before entering input, at least for login and password, because if you don't telnet clear input before reading and discards your inputs
Here is an example that allowed me to telnet to my own machine :
sh << EOF | telnet -X SRA localhost
sleep 2
echo my_user_name
sleep 1
echo my_password
# sleep 1 # looks like it can be removed
echo echo foo and bar
sleep 1
EOF
It correctly logs me into my box, executes echo foo and bar (essential command :-) ) and disconnects
Now why you should never do that :
you write a password in clear text in a script file which is poor security practice
you use telnet to do batch processing when it is not intended to be used that way : the script may not be portable to another telnet version
If you really want to pass command in a batch way to a remote server, you should instead try to use ssh which :
has options to process authentication securely (no password in script, nothing in clear text)
is intended to be used in batch mode as well as interactively
If you cannot use ssh (some sysadmin do not like to have uncontrolled input ssh connections) you could also try to use rsh. It is older, far less secure, but at least was designed for batch usage.
Thanks to Harvix answer, I got knew that there is also expect alternative native for shell, called sexpect. Get it from here. Then create this script (I call it telnetpass):
#!/bin/bash
# This script is used for automatically pass authentication by username and password in telnet prompt
# Its goal is similar as sshpass, but for telnet, so I call it telnetpass
. ~/.private/cisco_pw # should contain PASSWORD variable
export SEXPECT_SOCKFILE=/tmp/sexpect-telnetpass-$$.sock
sexpect spawn telnet $1
sexpect expect -cstring 'Username:'
sexpect send -enter $USER
sexpect expect -cstring 'Password:'
sexpect send -enter $PASSWORD
sexpect interact
Then you can run: telnetpass Host125 and got pass the authentication automatically
Trying 198.51.100.78 ...
Connected to Host125.
Escape character is '^]'.
User Access Verification
Username: ashark
Password:
host-125>
I like this solution more than using sleep commands as suggested in another answers, because sleep solutions sometimes fail.
Have you tried using the expect command ?? You will have to create a script where you identify the 'expected' response from the server e.g. 'Password:' and then supply the password in the script. The following will explain: https://en.wikipedia.org/wiki/Expect - A good example is also shown here: http://en.kioskea.net/faq/4736-shell-script-for-telnet-and-run-commands
Try eval:
eval "{ echo;
sleep 3;
echo $user;
sleep 1;
echo $pass;
sleep 1;
echo '?';
sleep 1; }" | telnet your_host
In this example, my remote command is '?' (help).
The sleeps (maybe not all of them nor these times; trial-error...) are needed to avoid telnet misses some inputs.
The user and password are passed as variables ($user and $pass). Take into account security recommendations to store the password if you are scripting.
I want to remotely excute a program tcp_sender with root priviledge
,the following function is for making a ssh connection
def connect(hostname):
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(hostname, username='usr', pkey=paramiko.RSAKey.from_private_key(open('id_rsa'), 'psw'), timeout = 240.0)
return ssh
then I have 3 solutions:
solution A)
ssh = connect(hostname)
chan = ssh.invoke_shell()
chan.send('sudo ./tcp_sender\n')
with this solution, the remote tcp_sender is not executed, I checked using ps -ef|grep "tcp_sender", there is no process
I tried chan.send('sudo ./tcp_sender > log 2>&1\n')
and in the log, it says:
sudo: no tty present and no askpass program specified
solution B)
ssh = connect(hostname)
(stdin, stdout, stderr) = ssh.exec_command("[ -f tcp_sender ] && echo 1 || echo 0")
res = stdout.readlines()
print hostname,res[0]
if res[0] == '0\n':
UnusedHostFile.write(hostname+'no tcp_sender exists\n')
else:
chan = ssh.invoke_shell()
chan.send("sudo chmod 777 tcp_sender\n")
# if a tcp_sender is runnning, kill it
chan.send('x=`ps -ef|grep "tcp_sender"|grep -v "grep"|awk \'{print $2}\'`; [ -n "${x}" ] && sudo kill -9 $x\n')
time.sleep(4)
while not chan.recv_ready():
time.sleep(1)
buf = ''
buf +=chan.recv(9999)
print buf
chan.send('sudo ./tcp_sender\n')
with this solution, I just add some un-relevant lines, then the remote tcp_sender is running, something like:
bash-4.0# ps -ef|grep "sender"
root 9348 9325 0 Apr07 ? 00:00:00 sudo ./tcp_sender
root 9349 9348 0 Apr07 ? 00:00:00 ./tcp_sender
however, it can't run normally(as expected). In the tcp_sender, there is a fork(), maybe it is due to this?
I tried chan.send('sudo ./tcp_sender > log 2>&1\n')
and in the log, it is empty. Because I have many error-checking related printf in my tcp_sender program, I think there should be printf results in the log, but it is empty.
In addition, I noticed a phenomenon, if I kill -9 9348, all these two processes are ended.
But for the next solution C, the process 9349 will be handed over to system init process 1.
Solution C):
with this solution, I can run the remote tcp_sender correctly. But the python script will be blocked by the remote program until it exits. I don't want my script to wait that the remote exits.
log = open('log','a+')
ssh = connect(hostname)
(stdin, stdout, stderr) = ssh.exec_command("[ -f tcp_sender ] && echo 1 || echo 0")
res = stdout.readlines()
print hostname,res[0]
if res[0] == '0\n':
UnusedHostFile.write(hostname+"tcp_sender doesn't exists\n")
else:
chan = ssh.invoke_shell()
chan.send("sudo chmod 777 tcp_sender\n")
chan.send('x=`ps -ef|grep "tcp_sender"|grep -v "grep"|awk \'{print $2}\'`; [ -n "${x}" ] && sudo kill -9 $x\n')
time.sleep(4)
while not chan.recv_ready():
time.sleep(1)
buf = ''
buf +=chan.recv(9999)
print buf
chan.send('sudo ./tcp_sender\n')
#chan.send('sudo whoami\n')
time.sleep(2)
(stdin, stdout, stderr) = ssh.exec_command("ps -ef|grep 'tcp_sender'|grep -v 'grep'|wc -l")
res = stdout.readlines()
while res[0].strip() != '0':
time.sleep(3)
(stdin, stdout, stderr) = ssh.exec_command("ps -ef|grep 'tcp_sender'|grep -v 'grep'|wc -l")
res = stdout.readlines()
print res[0].strip()
while not chan.recv_ready():
time.slepp(1)
buf = ''
buf += chan.recv(9999)
log.write(hostname+': '+''.join(str(elem) for elem in buf)+'\n\n')
log.close()
so what are potential reasons for this phenomenon?
can anyone give some advice? thanks!
You're mixing things that you should probably keep separate.
First, write a script on the remote side that usr (= username that you give paramiko) can execute and which can correctly start tcp_sender using sudo without asking for a password, etc.
In the script, start sudo as background process using nohup:
nohup sudo ./tcp_sender
nohup makes sure that the new child process is properly detached so it stays alive when the connection is lost/cut.
When this script works, start the new script using ssh.exec_command('script')
Reasoning: It's probably possible to do what you want using a shell and clever Python code that drives the shell as if you were typing the commands. But it will always be brittle, hard to test - it's a variant of the God object.
Instead, split your problem into small, distinct problems that you can develop and test independently. You have three problems to solve:
tcp_sender itself.
Starting tcp_sender
Starting it remotely
so use three distinct tools to solve them.
Agreed with other comment - you are mixing issues which can be solved separately. Many people (including myself) have made this error.
Paramiko is powerful, and smart: it can navigate and respond to SSH username and password prompts. But this is a special case. Most of the time when you need to respond to a PROMPT in Paramiko, you basically wait then shoot text at the assumed prompt. This is messy.
This also has absolutely nothing to do with your real problem.
What you want to do is edit /etc/sudoers file so that your automation test user or group is able to run the precise command you want using NOPASSWD.
Let's say I want to remotely grep /var/log/auth.log on host "ServerB". While grep can be run by any user, it's known that auth.log on this system is only readable by user root. SO:
1) My test user is "scott", and a member of group "adm. See /etc/groups and /etc/passwd. Basic stuff.
2) /etc/sudoers:
%adm ALL=(ALL)NOPASSWD:/bin/grep
3) From a remote system, I run:
$ ssh scott#ServerB "sudo grep Accepted /var/log/auth.log"
2013-10-14T21:17:54+00:00 proc4-01-us1 sshd[28873]: Accepted publickey for scott from x.x.x.x port 56799 ssh2
2013-10-14T21:19:16+00:00 proc4-01-us1 sshd[29367]: Accepted publickey for scott from x.x.x.x port 56804 ssh2
2013-10-14T21:19:21+00:00 proc4-01-us1 sshd[29519]: Accepted publickey for scott from x.x.x.x port 56805 ssh2
Bang, you're done.
NOTES
DO use an absolute filesystem path to the script you specify in sudoers.
DO use SSH keys. You can use keys +passphrase if you like. (Remember, Paramiko can answer login prompts) But this also means storing your passphrase in the script...
DO consider security. You're not really lessoning security here if you attach this permission to a special user. Certainly the method I describe is more secure than hardcoding a sudo password into the script.
DON'T use NOPASSWD:ALL except in testing. Specify what is allowed explicitly.
DO consider adding restrictions to what these users can run. For example, if I'm always running this test from an EC2 box, I'd only allow that user to connect from that EC2 IP. Conversationally, I could restrict what commands can be run by a user by adding prefixes in "authorized"keys" (ie, restricting that user to only being able to run rsync command, if I wanted to avoid running an rsync server full-time for example).
Here's the context of the question:
In order for me to be able to print documents at work, I have to copy the file over to a different computer and then print from that computer. (Don't ask. It's complicated and there is not another viable solution.) Both of the computers are Linux and I work in bash. The way I currently do this is I scp the file over to the print computer and then ssh in and print from command line.
Here's what I would like to do:
In order to make my life a bit easier, I'd like to combine these two step into one. I could easily write a function that did both these steps, but I would have to provide my password twice. Is there any way to combine the steps so that I only provide my password once?
Before somebody suggests it, key-based ssh-logins are not an option. It has been specifically disabled by the Administrators for security reasons.
Solution:
What I ended up doing was a modification of the second solution Wrikken provided. Simply wrapping up his first suggestion in a function would have gotten the job done, but I liked the idea of being able to print multiple documents without having to type my password once per document. I have a rather long password and I'm a lazy typist :)
So, what I did was take a sequence of commands and wrap them up in a python script. I used python because I wanted to parameterize the script, and I find it easiest to do in python. I cheated and just ran bash commands from python through os.system. Python just handled parameterization and flow control. The logic was as follows:
if socket does not exist:
run bash command to create socket with timeout
copy file using the created socket
ssh command to print using socket
In addition to using a timeout, I also put have an option in my python script to manually close the socket should I wish to do so.
If anyone wants the code, just let me know and I'll either paste-bin it or put it on my git repo.
ssh user#host 'cat - > /tmp/file.ext; do_something_with /tmp/file.ext;rm /tmp/file.ext' < file.ext
Another option would be to just leave an ssh tunnel open:
In ~/.ssh/config:
Host *
ControlMaster auto
ControlPath ~/.ssh/sockets/ssh-socket-%r-%h-%p
.
$ ssh -f -N -l user host
(socket is now open)
Subsequent ssh/scp requests will reuse the already existing tunnel.
Here is bash script template, which follows #Wrikken's second method, but can be used as is - no need to edit user's SSH config file:
#!/bin/bash
TARGET_ADDRESS=$1 # the first script argument
HOST_PATH=$2 # the second script argument
TARGET_USER=root
TMP_DIR=$(mktemp -d)
SSH_CFG=$TMP_DIR/ssh-cfg
SSH_SOCKET=$TMP_DIR/ssh-socket
TARGET_PATH=/tmp/file
# Create a temporary SSH config file:
cat > "$SSH_CFG" <<ENDCFG
Host *
ControlMaster auto
ControlPath $SSH_SOCKET
ENDCFG
# Open a SSH tunnel:
ssh -F "$SSH_CFG" -f -N -l $TARGET_USER $TARGET_ADDRESS
# Upload the file:
scp -F "$SSH_CFG" "$HOST_PATH" $TARGET_USER#$TARGET_ADDRESS:"$TARGET_PATH"
# Run SSH commands:
ssh -F "$SSH_CFG" $TARGET_USER#$TARGET_ADDRESS -T <<ENDSSH
# Do something with $TARGET_PATH here
ENDSSH
# Close the SSH tunnel:
ssh -F "$SSH_CFG" -S "$SSH_SOCKET" -O exit "$TARGET_ADDRESS"