I am trying to write a python script which uses scp to log into a HPC cluster (where I have an account) and transfer files from the cluster to my local system. I am able to os.system() to type the scp command. But, after that, I am a bit confused about what I must do when I am asked for the password (assume my password is password). I have tried os.system('password') and print 'password', but they don't work.
This is the python script that I have written:
import os
import sys
password = 'password'
clusterpath = 'myname#cluster.hpc1.cs.univ.edu:/Projects/re* '
localpath = 'Projects/.'
os.system('scp ' + clusterpath + localpath)
When I execute this script, I am asked for the password of my cluster. How can I enter the password of the cluster account through this python script?
Related
I have created GuI in Visual Studio 2019.
There user will enter username and password and that i have to pass to python script. That when user will click on login button, python script will be triggered and output will be displayed.
My Tried python code is:
import paramiko
import time
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
try:
hostname = input("Enter host IP address: ")
username = input("Enter SSH Username: ")
password = input("Enter SSH Password: ")
port = 22
ssh.connect(hostname, port, username, password, look_for_keys=False)
print("ssh login successfully")
#stdin,stdout,stderr = ssh.exec_command('show version')
#output = stdout.readlines()
#print(output)
Device_access = ssh.invoke_shell()
Device_access.send(b'environment no more \n')
Device_access.send(b'show version\n')
time.sleep(2)
output = Device_access.recv(65000)
print (output.decode('ascii'))
except:
print("error in connection due to wrong input entered")
But in this i am not getting how to link with input enter to Gui c# with python script. Please let me know how i can do.
Thanks in advance!
You could use arguments to call your Python Script.
Change the python script:
import paramiko
import time
import sys # Used to get arguments
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
try:
hostname = sys.argv[1] # Skip 0th arg, since it is just the filename
username = sys.argv[2]
password = sys.argv[3]
port = 22
ssh.connect(hostname, port, username, password, look_for_keys=False)
print("ssh login successfully")
#stdin,stdout,stderr = ssh.exec_command('show version')
#output = stdout.readlines()
#print(output)
Device_access = ssh.invoke_shell()
Device_access.send(b'environment no more \n')
Device_access.send(b'show version\n')
time.sleep(2)
output = Device_access.recv(65000)
print (output.decode('ascii'))
except:
print("error in connection due to wrong input entered")
And change your C# code which calls the Script to something like this:
Process pythonScript = new Process();
pythonScript.StartInfo.FileName = "Your python script";
pythonScript.StartInfo.Arguments = $"{YouHostnameVar} {YouUsernameVar} {YourPasswordVar}"; // Start the script with the credentials as arguments
pythonScript.Start();
There are multiple approaches to incorporating a Python script with .NET C# code
I will try and give a basic overview, along with my suggestion, but ultimately, it will be up to you to figure out what works best.
IronPython
IronPython is an actual separate interpreter to translate Python code into the .NET Common Language Runtime (CLR). It works well for simple Python2 scripts that are not reliant on certain libraries.
Python.NET
Python.NET uses the normal Python interpreter. It simply provides a way to interface between Python scripts and .NET code.
System Diagnostics (My Suggestion)
The System Diagnostics C# tool allows you to run Python scripts as a system process. Not that this only runs the Python script. In order to transfer information between the Python script and the C# code, you will need some kind of shared file. I recommend setting up a folder where you save information used by both the C# and Python programs.
For a simple implementation of System Diagnostics, along with notes on the particular way System Diagnostics is being called, check out this: https://www.dotnetlovers.com/article/216/executing-python-script-from-c-sharp
EDIT Based on Paul Sütterlin Answer
As opposed to using a file to share information, Paul correctly points out that you can pass information as arguments. He also points out the simple process tool in C#, which is easier to set up than System Diagnostics. I recommend you read the article I linked to see which solution best suits you. System diagnostics gives you more options, but they do have to be configured.
Right now, I'm connecting to the ftp in bash using
echo "
user $USER1 $PASS1
user $USER2 $PASS2
user $USER3 $PASS3"|ftp -n $FTPSERVER
I tried to handle this in python using
ftp = ftplib.FTP(SERVER)
ftp.sendcmd("user {} {}".format(USER1, PASS1))
ftp.sendcmd("user {} {}".format(USER2, PASS2))
...
When I connect using bash, the output is
However, when I try using python, the first line only gives output "331 Password: " and if I send anymore commands, it gives the error Please supply password with PASS command.
Also, I'm not sure if it's relevant but $USER2 and $PASS2 have # in them with $PASS2 beginning with it.
This question already has answers here:
I need to securely store a username and password in Python, what are my options? [closed]
(8 answers)
Closed 6 years ago.
So this is my code: https://github.com/trisimix/serialcontrol/blob/master/serialcontrol.py
import subprocess
import os
import stat
dmi = subprocess.check_output('dmidecode', shell=True)
#print(variable)
#run program once as root then cron it as root
try :
file = open("/var/log/serialcontrol/dmidecode.txt", "r")
file.close()
except FileNotFoundError:
script = '/var/tmp/serialcontrol.bash'
with open(script, 'w') as file:
file.write("#!/bin/bash/\nif [ ! -d /var/log/serialcontrol/ ]\nthen\n\tmkdir /var/log/serialcontrol/\nfi");
#st = os.stat(script)
#os.chmod(script, st.st_mode | stat.S_IEXEC)
subprocess.call(["bash", script])
subprocess.call(["rm", script])
#with open('/var/log/serialcontrol/dmidecode.txt' , 'w') as file:
# file.write(dmi);
file = open("/var/log/serialcontrol/dmidecode.txt" , "w");
dmi = str(dmi)
dmi = dmi.replace('\\n', '\n')
dmi = dmi.replace('\\t', '\t')
file.write(dmi)
file.close()
script2 = '/var/log/serialcontrol/serialcontro1.bash'
#with open(script2, 'w') as file:
# file.write('#!/bin/bash\nrecipients="archmachine9#gmail.com"\nsubject="...Subject..."\necho -e "to: $recipients\nsubject: $subject\n"| (cat - &&uuencode /var/log/serialcontrol/dmidecode.txt) | ssmtp archmachine9#gmail.com')
import smtplib
sender = 'archmachine9#gmail.com'
receivers = 'archmachine9#gmail.com'
message = "\r\n".join([
"From: archmachine9#gmail.com",
"To: archmachine9#gmail.com",
"Subject: SerialControl",
"",
dmi
])
username = 'archmachine9#gmail.com'
password = ''
server = smtplib.SMTP('smtp.gmail.com:587')
server.ehlo()
server.starttls()
server.login(username,password)
server.sendmail(sender, receivers, message)
server.quit()
#subprocess.call(["bash", script2])
#this sub is supposed to /n with actual /n's
#subprocess.run(["sed -i 's/\\n/\n/g' /var/log/serialcontrol/dmidecode.txt"], shell=True)
#except FileNotFoundError:
#file = open('/var/tmp/serialcontrol.bash', 'w')
#file.write("#!/bin/bash/\nif [ ! -d /var/log/serialcontrol/]\nthen\n\tmkdir /var/log/serialcontrol/\nfi");
#file.close()
#st = os.stat("/var/tmp/serialcontrol.bash")
#os.chmod("/var/tmp/serialcontrol.bash", st.st_mode | stat.S_IEXEC)
#subprocess.call("/var/tmp/serialcontrol.bash")
I know it's really, really, really, really, REALLY, bad but in the password segment I have to type my password before I cron this script and the password gets stored as plaintext, how fix?
As you tagged the question with bash I shall assume that you use a Linux or Unix-like system.
That is what I would call a machine password. If you want it to be used from a script launched via cron, it must be accessible somewhere on the disk.
The correct (or less bad) way is to:
use a dedicated mail account for that usage - not you personal mail account (but archmachine9 is a hint that you have already done that...) - ideally it should be impossible to login with this account (a single*` in the password field for example)
use a system account on the machine - neither root nor you main local account
store the password in a file located under the home directory of that system account. The password should be read/write only for owner
extract the username, password and eventually server from the environment
if you cannot find one of them, read them from the file
alternatively embed the script in a launcher that read the credentials from the file, and put them in the environment before starting the real script (my favorite option)
That way, even if the mail account is shared over different scripts, you will have one central point to change the password, and as it is stored in a file only accessible to a system account, only the machine admin (root) should be able to read it. And you do not have to know it to develop, maintain and test the script, you will just have to put a test mail account in your dev environment
TL/DR: the password has to be stored as plaintext on the machine for the script to be launchable via cron, but it shall not be in the script itself
I need to connect to a remote server using a (non-python) script from terminal.
$./myscript <parameters>
Normally, I would need to enter the password. I have the following question, assuming a python script will run myscript:
How do I get the password from the user
How do I feed it into myscript?
If I understand the question correctly you would probably use the getpass function.
import getpass
password = getpass.getpass()
print 'You entered:', password
The major advantage is that the password will not be visible on the screen as the user enters it.
If you simply want to pass in arguments to your application you can use sys.argv.
import sys
if len(sys.argv) > 1:
print "First argument:", sys.argv[1]
If you need to pass on a password to a script executed by Python you can use subprocess call.
import getpass
import subprocess
password = getpass.getpass()
subprocess.call(["myscript", password ])
I am working on a project that requires us to upload a vile via SFTP to a remote server, and we are having troubles doing this. We tried following this youtube guide, but we are having some issues.
We are getting a "no such file" error when we run the script, and we know for sure that the file exists and that we have given the python script the right name and location for the file.
This is the script as we have it right now:
import pysftp as sftp
def sftpTry():
try:
s = sftp.Connection(host='babbage.cs.missouri.edu', username ='<username>', password = '<password>')
remotepath = '~it3001s14grp1/videos/newVideo/new.avi'
#localpath = '/etc/motion/capture/hello.txt'
localpath = '/etc/motion/capture/06--2014-05-15---16-16-25.avi'
s.put(localpath, remotepath)
s.close()
except Exception, e:
print str(e)
sftpTry();
You should begin your remote path with a forward slash "/". Also, check the directory you are specifying in the remotepath. You should try to do a pwd in the directory when you login into the server (say using ssh). The remote-path should be specified exactly like that.
Although you do have the filename name in the remote path, it would throw an error if you specify just the folder's name.
Another tip would be to use getpass instead of hard-coding the password:
passwd = getpass.getpass()
s = sftp.Connection(host='<host>', username = '<username>', password = passwd)