Executing commands on remote machines
This post comes from a request from one of my friends on discord. We will go over how to setup
a python script that can connect to a remote machine, execute commands, and reutrn the output
back to you. And then a little bit on how to parse that output. I will also show how to use the
remote server how run commands on another machine that is behind the remote server.
For the purpose of this diminstartion, we will use "Local" to refer to our pc. "Server_IP" will
refer to the remote server's IP address. Finally, "Remote_Device_IP" will refer to the remote
machine that is on a network behine the remote server. Also, I will be using Notepad++ for writing
this code as well.
For the frirst part we need to import three key libraries. Getpass, paramiko, and time.
Please not you may need to run pip to install paramiko.

From here you can structure your code however you like. For the purpose of this example, I will
keep it simple. I am just going to build this as a one time pass through with no function calls.
Next we will setup our client, set a host key policy, and get the username and password form the
user that is needed to connect to the server.

Optional step is to get the remote server IP and port if you don't want to hard code them in. For
the rest of this example we will work with this optional input.

Next we need to establish the connection to the remote server.

Now for a couple of examples. First we will grab the hostname of the server.

First we tell it we want to execute the command hostname using the "client.exec_command()" command.
I have it hear for stdin, stdout, and stderr to all send/recieve from this. This is just something
I do everytime regardless of what I am doing. I find it works best to have this as a common practice.
Then we read from stdout and decode it. It gets passed back as a byte string. By decoding, it gets
turned into a normal string. Then we strip the newline at the end of the output. Then we simple
print it out using an f-string.
The next example will be to pull the current CPU temps. This is stored in a temporary file in the
/sys/class/thermal folder. This is where most if not all sensors will store info on linux systems.
Note that the number of the folder name "thermal_zone1" may need to be changed for your machine.
Each zone has a temp and a type file. You can check the type file for CPU to know oyu have the right
one.

We are going to use the "client.exec_command" toll again. This time we want it to cat the temp file
and the we will use some sed magic to make it an actual temp out put. The normal output isn't
formated and has zeros after it. So if the temp is 79C, in the file that would look like 79000.
Then, like, before, we read the output, decode it, and strip the trailing newline. Finally print
it out with the server name.
Lastly, we will have the code connect to a remote device thorugh the remote server and retrive
the root partition usage size. There are several parts to this. First we will gatehr the information
from the user that we need to make the connection. I have the user supplying the remote port, but
you can leave this out and not have the port option in the next section. It will use the default
22 port in that case.

Next we will invoke a shell on the remote server to that we can runs commands as if they where
ran on the server. I find it easier to handle this type of work using the "client.invoke_shell()"
as to the method we used for the last two examples. Then we send our command for the server to ssh
into the remote device and run the df command. We parse the output fo the df command with to grep
statments. The first one uses the switch "-v" to remove lines with the loop keyword. The second one
will look for only lines that have the dev keyword.
Please note the \' in the df command. We need
these here so python will not read these parts as strings, but knows to actually send a single quote.
If we didn't, the first single quote before the loop keyword. would close out string we are sending
and raise an error when we ran out code. Lastly, we sleep for two seconds to give the time needed
to setup the connection and recieve our first bit of output. Also, the command is passed as a r-string.
This is a 'raw string'. This tells python to ignore the slashes basically.

Next we recieve from the connection with a 9999 character buffer. It is overkill, but I like to
have more then I expect I will need. We check the output for the yes/no you would see if it was your
first time connecting to a device through ssh. If it is found we will send yes reply with a newline
to act as us using the enter key. Then we wait five seconds to allow it time to add the device
fingerprint to our known_hosts file.

Next, we need to send the remote device password we got from out input. Then wait two seconds for it to
log us in.

For the last bit we will recieve the output of the command we passed back on line 37. there is a
split('\r') after decodeing the recved output. This was from trial and error. The nice thing is you
can skip the decode part and print the byte string. This will show any escape characters like the
\r and \n. Then we have a for loop that splits each line of the output on the space character and
make it a list. We check the last item in the list using the [-1] for just the / character. This
indicates the root drive we are looking for. You could add an or statment here if you wanted to look
for a /boot drive or any other custome partions you have in your setup.
Once we find the root drive, we will split that enter on the space charater as well to make a new
list. Then grab the second to last item in the new list. This will normally be your disk usage in the
output. You can always check this by running the command on the remote device and comparing it to
the byte string information that we get. Finally we print out the usage with the server name via an
f-string.

I hope you enjoyed this walkthrough and where able to learn from it. Below you can find a link to
the code used in this post on my github. I encourage you to experament with your on machines to see
what all you can do with this script. Good luck and thank you for taking the time to read.
Code Link
