this is for work... so i will share as much as i can, I'm trying to install "environment" on a remote machine via python script, this "environment" require to pass to it user name and password, I tried a lot of things, nothing seems to work... the closest thing is this script, yet after it passes the user name a GUI popup and ask for the password... what i'm doing wrong ?! or what can i do to make it work?!... here is a part of the script that deal with pexpect
import os
import pexpect
cmd = 'ssh -X groupName#machineName cd ~/theLocationOfTheInstallation/ && pwd && theFullPathOfTheFileToInstall'
child = pexpect.spawn(cmd)
cmd_show_data = ''
usr = 'userName'
pas = 'myPassword'
while not child.eof() :
index = child.expect(['Please enter your.*','pass.*', pexpect.EOF, pexpect.TIMEOUT])
cmd_show_data += child.before
child.delaybeforesend = 1
if index == 0 :
print 'user name required, "'+usr+'" is passed'
child.sendline(usr)
elif index == 1 :
print 'password required, "'+pas+'" is passed'
child.sendline(pas)
elif index == 2 :
print 'EOF'
elif index == 3 :
print 'TIMEOUT'
cmd_show_data += child.before
cmd_show_data = cmd_show_data.split('\r\n')
for s in cmd_show_data :
print s
this is the GUI that popup :
if i enter the password manually (which i'm trying to avoid), i get output like this :
user name required, "userName" is passed
TIMEOUT
TIMEOUT (a lot of times out)
user name required, "userName" is passed
TIMEOUT
TIMEOUT (a lot of times out)
password required, "myPassword" is passed
TIMEOUT
TIMEOUT (a lot of times out).... till the installation is complete.
so.. any ideas?
If you really want to do this job with only Python, why can't you use Ansible instead?
Ansible solution:
If you have a script which installs software locally, then run that script in remote servers with the Ansible script module
# Example from Ansible Playbooks
- script: /some/local/script.py 1234
Python file example :
#!/usr/bin/python
import sys
print 'Number of arguments:', len(sys.argv), 'arguments.'
print '1st Argument :', str(sys.argv[1])
Here are some documentation links:
http://docs.ansible.com/ansible/script_module.html
http://docs.ansible.com/ansible/intro_adhoc.html
Related
trying to use python to automate a usage of a command line application called slsk-cli
manually, the procedure is straight-forward - i open a command prompt window and type 'soulseek login', then a prompt requests username, after i type in and press enter i'm requested a password.
so far, i manage to get the prompt of the username but not getting passed that.
subprocess.run('soulseek login',shell=True)
this results in the ?Login output in the python console but also the process is stuck, when i run in debug or also in run
is there a better way to go about this?
Interacting continuously with a system via subprocess can be tricky. However, it seems that your interface prompts are one after the other, which can therefore be chained together, via newline characters which act as Return key strokes.
For example, the program shown below simply prompts a user for their username and a password, to which the 'user' (your script) provides the input via the proc.communicate() method. Once these are provided, the user is asked if they'd like to continue (and do the same thing again). The following subprocess call feeds the following input into the prompter.py script:
username
password
continue reply (y or n)
Example code:
import subprocess
uid = 'Bob'
pwd = 'MyPa$$w0rd'
reply = 'n'
with subprocess.Popen('./prompter.py',
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
stdin=subprocess.PIPE,
text=True) as proc:
stdout, stderr = proc.communicate(input='\n'.join([uid, pwd, reply]))
Output:
# Check output.
>>> print(stdout)
Please enter a username: Password: uid='Bob'
pwd='MyPa$$w0rd'
Have another go? [y|n]:
# Sanity check for errors.
>>> print(stderr)
''
Script:
For completeness, I've included the contents of the prompter.py script below.
#!/usr/bin/env python
from time import sleep
def prompter():
while True:
uid = input('\nPlease enter a username: ')
pwd = input('Password: ')
print(f'{uid=}\n{pwd=}')
sleep(2)
x = input('Have another go? [y|n]: ')
if x.lower() == 'n':
break
if __name__ == '__main__':
prompter()
#! python3
# pw.py - An insecure password locker program.
PASSWORDS = {'email': 'F7minlBDDuvMJuxESSKHFhTxFtjVB6',
'blog': 'VmALvQyKAxiVH5G8v01if1MLZF3sdt',
'luggage': '12345'}
import sys, pyperclip
if len(sys.argv) < 2:
print('Usage: py pw.py [account] - copy account password')
sys.exit()
account = sys.argv[1] # first command line arg is the account name
if account in PASSWORDS:
pyperclip.copy(PASSWORDS[account])
print('Password for ' + account + ' copied to clipboard.')
else:
print('There is no account named ' + account)
I really don't know what to do. After running win+r and typing e.g. pw email i get only 'usage:py bla bla bla.. nothing else whatever i wrote in win+r
the bat file is like:
'''call C:\Users\Rostek\anaconda3\Scripts\activate.bat
C:\Users\Rostek\anaconda3\python.exe "C:\Users\Rostek\.spyder-py3\Projekty\pw.py"
#pause'''
I cannot pass the arguments I think. I have read all the internet and found nothing like this.
please help. It's program from the book. I am using anaconda3.
You might want to think about what your problem is supposed to do.
if len(sys.argv) < 2:
print('Usage: py pw.py [account] - copy account password')
sys.exit()
This clearly does what it should.
Your question is actually not about python, but about win+r passing arguments.
Why do you want to run your program with win+r in the first place?
After running win+r and typing e.g. pw email...
What you want is to open the command line/ powershell/ bash instead and simply pass the variables to your programm with python3 programname.py email directly.
If you want to do that even cleaner you should use an argparser.
EDIT:
After the clarification in the comments:
The problem is that if you execute a script with win+r you will get the output- for a fraction of a second- then the cmd is closed...
So unless you specify a location in your script to where the pw is written to, you´ll have it in your console. Which blinks and vanishes immediately. Therefore open a console and execute the program from there.
Or you might want to have a look at this:
Output to clipboard
I want to detect if the user is connected over SSH. In a term, the "env" command shows SSH_CONNECTION line. Accessed in Python in one of two ways:
#python:
import os
print os.getenv("SSH_CONNECTION") #works
print os.environ.get("SSH_CONNECTION") #works
But, if the user has ran my program using SUDO (as they will need to), env$ dooesn't show SSH_CONNECTION. So Python can't see it:
#sudo python:
import os
print os.getenv("SSH_CONNECTION") #not set
print os.environ.get("SSH_CONNECTION") #not set
The aim is to achieve the following:
#Detect if user is over remote IP
lRemoteIP="" #Is set if user on SSH
lStr=os.environ.get("SSH_CONNECTION") #Temp var
if lStr: lRemoteIP=lStr.split()[0].split("=")[1] #Store user's lasthop IP
#Later on in the code, for multiple purposes:
if lRemoteIP: pass #Do stuff (or not) depending on if they're on SSH
How do I retrieve SSH_CONNECTION environment variable under SUDO, when its not present in env$ ?
Or more precisely: how can I detect if the current session is via SSH when sudo?
I'm not a natural at Linuxy-type things, so be gentle with me...
[EDIT:] METHOD 2: Giving up on env$, I've tried the following:
pstree -ps $$ | grep "sshd("
If it returns anything then it means that the SSH daemon sits above the session. Ergo, it's a SSH connection. And the results are showing me the PIDs of the SSH daemons. Results of the pstree cmd:
init(1)---sshd(xxx)---sshd(xxx)---sshd(xxx)---bash(xxx)-+-grep(xxx)
But I'm struggling to get a src IP from the PID. Any ideas on this avenue?
[EDIT] METHOD 3: /run/utmp contains details of SSH logins. In python:
import os
import sys
lStr=open("/var/run/utmp").read().replace('\x00','') #Remove all those null values which make things hard to read
#Get the pseudo-session ID (pts) minus the /dev/ that it starts with:
lCurSess=os.ttyname(sys.stdout.fileno()).replace('/dev/','')
#Answer is like pts/10 (pseudo-term session number 10)
#Search lStr for pts/10
lInt=lStr.find(lCurSess.replace('/dev/',''))
#Print /var/utmp starting with where it first mentions current pts:
print lStr[lInt:]
So far, so good. This gives the following results (I've changed the IP and username to USERNAME)
pts/10/10USERNAME\x9e\x958Ym\xb2\x05\x0 74\x14pts/10s/10USERNAME192.168.1.1\xbf\x958Y\xf8\xa3\r\xc0\xa88\x01
So, when it comes to extracting the IP from the file, there's some bumf inbetween the occurances of pts/10 and the IP. What's the best way to parse it, given that (I reckon) the precise distance from the match to the IP will be different under different circumstances?
The OpenSSH daemon writes an entry to /var/run/utmp with the current terminal, the IP and the name of the user. Check the output of the w or who commands that parse /var/run/utmp.
It's just a question of getting the current terminal (similar to the tty command) and extracting the information you want.
Use pyutmp like this:
from pyutmp import UtmpFile
import os
import sys
for utmp in UtmpFile():
if os.ttyname(sys.stdout.fileno()) == utmp.ut_line:
print '%s logged from %s on tty %s' % (utmp.ut_user, utmp.ut_host, utmp.ut_line)
Then filter by using ut_pid field to parse the /proc/ut_pid/cmdline file which should contain:
sshd: ut_user [priv]
GOT IT AT LAST!!!
The "last" command has list of users and their IPs!! So simple.
It has "still logged in" marked against sessions. Filter by these
And then filter by current pts ID
To get the IP for the current SSH session in Python, do this:
import os,sys,subprocess
(out, err) = subprocess.Popen(['last | grep "still logged in" | grep "' + os.ttyname(sys.stdout.fileno()).replace('/dev/','') + '"'], stdout=subprocess.PIPE, shell=True).communicate()
RemoteIP=out.split()[2].replace(":0.0","") #Returns "" if not SSH
For readability, across multiple lines:
import os,sys,subprocess
pseudoTermID = os.ttyname(sys.stdout.fileno()).replace('/dev/','')
cmdStr = 'last | grep "still logged in" | grep "'+pseudoTermID+'"'
sp = subprocess.Popen([cmdStr], stdout=subprocess.PIPE, shell=True)
(out, err) = sp.communicate()
RemoteIP = out.split()[2].replace(":0.0","") #Returns "" if not SSH
I am able to write a script to checkout the code from SVN issue using "pysvn" module but just wanted to know is there any way I can do without pysvn also ? Because pysvn is third party library which I have to install separately on linux and windows both which I don't want. Please help me get alternate way in which I don't have to install any third party module code -
import pysvn,os,shutil
def getLogin(realm, username, may_save):
svn_user = '<my-username>'
svn_pass = '<my-password>'
return True, svn_user, svn_pass, False
def ssl_server_trust_prompt( trust_dict ):
return (True # server is trusted
,trust_dict["failures"]
,True) # save the answer so that the callback is not called again
def checkOut(svn_url,dest_dir):
if os.path.isdir(dest_dir):
shutil.rmtree(dest_dir)
os.mkdir(dest_dir)
client = pysvn.Client()
client.callback_ssl_server_trust_prompt = ssl_server_trust_prompt
client.callback_get_login = getLogin
client.checkout(svn_url,dest_dir)
else:
os.mkdir(dest_dir)
client = pysvn.Client()
client.callback_ssl_server_trust_prompt = ssl_server_trust_prompt
client.callback_get_login = getLogin
client.checkout(svn_url,dest_dir)
print "Checking out the code hang on...\n"
checkOut('<svn-repo>','ABC')
print "checked out the code \n"
print "Checking out the code hang on...\n"
checkOut('<svn-repo>','XYZ')
print "checked out the code\n"
print "Checking out the code hang on...\n"
checkOut('<svn-repo>','MNP')
print "checked out the code \n”
You can pass username and password as arguments:
$ svn update --username 'user2' --password 'password'
You can make Executable of ur script which will include the pysvn into binary file, thus wouldn't need to import or pip install any library, n ur code will run on python-less machines too
I have this Python3 code which use Pexpect.
import pexpect
import getpass
import sys
def ssh(username,password,host,port,command,writeline):
child = pexpect.spawn("ssh -p {} {}#{} '{}'".format(port,username,host,command))
child.expect("password: ")
child.sendline(password)
if(writeline):
print(child.read())
def scp(username,password,host,port,file,dest):
child = pexpect.spawn("scp -P {} {} {}#{}:{}".format(port,file,username,host,dest))
child.expect("password: ")
child.sendline(password)
try:
filename = sys.argv[1]
print("=== sendhw remote commander ===")
username = input("Username: ")
password = getpass.getpass("Password: ")
ssh(username,password,"some.host.net","22","mkdir ~/srakrnSRV",False)
scp(username,password,"some.host.net","22",filename,"~/srakrnSRV")
ssh(username,password,"some.host.net","22","cd srakrnSRV && sendhw {}".format(filename),True)
except IndexError:
print("No homework name specified.")
My aim is to:
SSH into the host with the ssh function, create the directory srakrnSRV, then
upload a file into the srakrnSRV directory, which is previously created
cd into srakrnSRV, and execute the sendhw <filename> command. The filename variable is defined by command line parameteres, and print the result out.
After running the entire code, Python prints out
b'\r\nbash: line 0: cd: srakrnSRV: No such file or directory\r\n'
which is not expected, as the directory should be previously created.
Also, I tried manually creating the srakrnSRV folder in my remote host. After running the command again, it appears that scp function is also not running. The only runnning pexpect coomand was the last ssh function.
How to make it execute in order? Thanks in advance!
You may lack permission for executing commands through ssh. Also there is possibility that your program sends scp before prompt occurs.