I've followed the steps here http://jessenoller.com/2009/02/05/ssh-programming-with-paramiko-completely-different/
to connect to my server with ssh via Python. I can connect fine and send commands.
When I run stderr.readlines(), however, it shows me the error message below every time, even if the command seems to have executed correctly. I've closed the connection and restarted Python, and still the same result.
Here's a Python sample:
>>> stdin, stdout, stderr = myssh.exec_command("xyz")
>>> stderr.readlines()
['which: no php in (/usr/bin:/bin:/usr/sbin:/sbin:/big/dom/mydomain/pear/drush)\n', '/big/dom/mydomain/pear/drush/drush: line 89: exec: : not found\n', 'bash: xyz: command not found\n']
I have drush installed and it seems to work fine. If I type in "which php" on the server I'm told where it resides, instead of the error message above. I sent some other commands to purposefully get an error message to see if it cleared anything out. Instead it tacked things on at the end.
Following the error message, I went and looked at the drush file referenced. Here's line 89:
exec "$php" $php_options "$SCRIPT_PATH" --php="$php" --php-options="$php_options" "$#"
I believe the "which php" command comes from the $php variable in the chunk above this line
if [ ! -z "$DRUSH_PHP" ] ; then
# Use the DRUSH_PHP environment variable if it is available.
php="$DRUSH_PHP"
else
# Default to using the php that we find on the PATH.
# Note that we need the full path to php here for Dreamhost, which behaves oddly. See http://drupal.org/node/662926
php=`which php`
# We check for a command line (cli) version of php, and if found use that.
which php-cli >/dev/null 2>&1
if [ "$?" = 0 ] ; then
php=`which php-cli`
fi
# On MSYSGIT, we need to use "php", not the full path to php
if [ ! -z "$MSYSTEM" ] && [ "x${MSYSTEM:0:5}" = "xMINGW" ] ; then
php="php"
fi
fi
The full text of the file is here: http://pastebin.com/29AXmHKF
I get the same error if I try to execute any drush command. But drush commands work fine if I just log myself into the server directly w/o using python/paramiko.
The first thing I had to understand is what the $PATH variable held at the time of executing the command. I ran
>>> stdin, stdout, stderr = myssh.exec_command("echo $PATH")
>>> stderr.readlines()
and realized my $PATH was not the same as when I run echo $PATH directly on the server! I can only guess that extra paths get appended to the $PATH variable at some point after the channel is opened and my command is sent.
However, what $PATH did contain was the path to drush which I previously added to the .bashrc file in my home folder. So, all I had to do was also add the path to php there as well (even though that path is there when I run "echo $PATH" on the server).
Now I don't get the error message and I can execute drush commands.
I used Mike Ryan's solution (thanks Mike!) but found the information in stdout, not stderr.
stdin, stdout, stderr = server.ssh_client.exec_command("echo $PATH")
print stdout.readlines()
What happens if you ssh to that server interactively and run xyz?
You only get to read the error message when you actually read it, not when you send the command. (Thank you, Captain.)
The error output looks very much like as if your xyz is a PHP script that starts with a #!which php shebang line. But the shell cannot find any PHP executable. This may be due to PATH not being set correctly in the login script. Make sure you understand which login script runs when you ssh to the box (usually it's ~/.bash_profile and/or ~/.profile and not necessarily ~/.bashrc).
Related
When I run this code:
import getpass
p = getpass.getpass(prompt='digite a senha\n')
if p == '12345':
print('YO Paul')
else:
print('BRHHH')
print('O seu input foi:', p) # p = seu input
I got this warning:
Warning (from warnings module):
File "/usr/lib/python3.4/getpass.py", line 63
passwd = fallback_getpass(prompt, stream)
GetPassWarning: Can not control echo on the terminal. Warning: Password input may be echoed.
Use an actual terminal -- that is, an environment where stdin, stdout and stderr are connected to /dev/tty, or another PTY-compliant device.
The IDLE REPL does not meet this requirement.
Run your code in terminal, instead of the IDE. you will see that there is no more warning there.
To run your code, enter this command in terminal:
python3 your_program.py
Rather than deal with changing the current working directory in a terminal that has not started Python (which would mean you type something like python3 script.py--and it will fail unless the current working directory is already specified), start Python in your terminal and run this one-line command:
exec(open('C:\folder\script.py').read())
where you change the path string 'C:\folder\script.py' to match wherever your file is located on disk (the string does need to be specified with quotes).
use cmd ie. command prompt and then run the file in it.
like:
python abc.py
How can I doc a specific terminal window on my Mac ( OS X 10.9.2) that upon clicking executes my python program from within shell script?
In my job.sh file I have this:
#!/bin/bash
python python_script.py
This is what I have in my python_script.py file:
import SimpleHTTPServer
import SocketServer
PORT = 8000
Handler = SimpleHTTPServer.SimpleHTTPRequestHandler
httpd = SocketServer.TCPServer(("", PORT), Handler)
print "serving at port", PORT
httpd.serve_forever()
Basically I don't want to have to open up my terminal window, type ./job.sh and run the command, I want my terminal window to run ./job.sh by default just by clicking it.
You can just put the command in your .profile or .bash_profile or .bashrc file:
echo 'python python_script.py' >> ~/.profile
# or
# echo '/path/to/job.sh' >> ~/.profile
When you open up a new terminal, the .profile file will be sourced and your job will be run.
Note: Command to be put into the file is python python_script.py or /path/to/job.sh
Figured it out! It was the .bash_profile file in my case(OS X) that needed the
'python python_script.py' >> ~/.bash_profile
command executed as my .profile is overlooked due to the order in which bash profile files are read. For anyone who has no idea about this(like me until today), definitely checkout http://hayne.net/MacDev/Notes/unixFAQ.html#shellStartup
The accepted answer for this question led me there, https://apple.stackexchange.com/questions/12993/why-doesnt-bashrc-run-automatically
After that, it was simply a matter of being in the right directory to execute the script.
Also be careful and make sure to properly exit out of your server(ctrl-c) when your done, as I closed out the workspace by accident before and it led to process being bound to the default port and kept giving me an error which was solved by this.
socket.error: [Errno 48] Address already in use
I'm trying to run a python script that will open a command prompt(OSGeo4W.bat is a command prompt line). I can get it to open but now I would like to send the command prompt commands.
import subprocess
myProcess = subprocess.Popen(['C:\OSGeo4W64\OSGeo4W.bat'],shell = False) #opens command prompt
myProcess.communicate('gdal2tiles -p raster -z 0-1 new.jpg abc')
myProcess.wait()
print("my process has terminated")
I've also tried
subprocess.check_call('gdal2tiles -p raster -z 0-1 new.jpg abc', shell=False)
I keep getting errors that say "WindowsError: [Error 2] The system cannot find the file specified"
although, if I were to keep the command prompt that it opens and type in " 'gdal2tiles -p raster -z 0-1 new.jpg abc' " then it will work just as I wanted. Help would be great, thanks!
Try:
check_call('gdal2tiles -p raster -z 0-1 new.jpg abc', shell=True)
shell=True changes how the executable is searched on Windows.
Or if gdal2tiles works only in the environment created by OSGeo4W.bat:
shell = Popen(r'C:\OSGeo4W64\OSGeo4W.bat', stdin=subprocess.PIPE)
shell.communicate('gdal2tiles -p raster -z 0-1 new.jpg abc')
# you don't need shell.wait() here
Notice: r"" literal. It is necessary to avoid escaping the backslashes in the path.
For those of you that are still trying to figure this one out, this is what I found. The "stdin=subprocess.PIPE" method above works with some command line tool in OSGeo4W64 but not all. It works with gdal_translate but not pdal translate for example. Not sure why;(
My Solution:
OSGeo4Wenv = r'CALL "C:/OSGeo4W64/bin/o4w_env.bat" '
pdal_translate_String = r'c:/OSGeo4W64/bin/pdal translate c:\inputFile c:\outputFile radiusoutlier --filters.radiusoutlier.min_neighbors=2 --filters.radiusoutlier.radius=8.0 --filters.radiusoutlier.extract=true'
Cmd = str(OSGeo4Wenv)+' & '+str(pdal_translateCmd)
shell = subprocess.call(Cmd, stdout=None, shell=True)
What is going on?
1) Open shell and set up the OSGeo4W environment by calling "OSGeo4Wenv". This is normally called by the OSGeo4W.bat file. Without this, the command line programs don't know where to look for the libraries.
2) The pdal_translate command is then sent to the dos shell because in Windows, multiple commands can be separated by the "&" symbol. I use the .call method of python 2.7. It has the advantage that it waits for the end of the process. That is nice if you use the multiprocessing map.pool method to launch multiple processes at the same time.
Hope this help others!
Nicolas
I'm trying pre-revprop-change hook script on a Windows machine, but find a tough problem.
I distill my problem to the following scenario:
I have C:\csvn\data\repositories\tr1\hooks\pre-revprop-change.bat with content:
D:\svntest\testhook.py %*
exit %ERRORLEVEL%
testhook.py is:
import os, sys
if __name__ == '__main__':
# sys.stderr.write(sys.version+'\n') # this is OK, tried.
newtext = sys.stdin.read() # try to read new log message
sys.stderr.write('newtext is: %s\n'%newtext)
exit(2)
However, when doing a client-side svn propset svn:log --revprop -r 2 "newtext" , I got python error:
Traceback (most recent call last):
File "D:\svntest\testhook.py", line 5, in <module>
newtext = sys.stdin.read() # try to read new log message
IOError: [Errno 9] Bad file descriptor
What's the cause of this error?
It seems that pre-revprop-change.bat does not pass STDIN handle to the py script. Yes, I verified that pre-revprop-change.bat can fetch text from STDIN(according to instructions in Read stdin stream in a batch file).
I also tried to run pre-revprop-change.bat directly from command line, sys.stdin.read() is OK.
Please kindly help me out.
Screen shot below:
Env:
Windows Server 2003
Collabnet Subversion Edge 2.3(svn 1.7.3 and Apache 2.2.22)
Install Python 2.7.1 msi from python.org
===============[LATEST UPDATE]======================
I'm sorry to say: I should have written in the .bat
exit %ERRORLEVEL%
instead of
exit /b %ERRORLEVEL%
For someone who have tried it with me, please fix it and try again. The /b seems to have pre-revprop-change.bat always exit with 0. TIP: Without /b, running the .bat directly from a cmd window will cause the cmd window to close, so we'd better try it with cmd /c "pre-revprop-change.bat some param".
Quick way to reproduce this problem below
What's more, for those who is still interested, please
download this file package http://down.nlscan.com/misc/chjsvnpyhook.zip ,
extract them to D:\ ,
cd into D:\svntest\tr1_local ,
run elog.bat (svn propset svn:log --revprop -r 2 "newtext")
then my problem will be reproduced. (Requirement: svn.exe 1.7 command line(whether collabnet or TortoiseSVN), and Python 2.7 installed)
If you still cannot reproduce the error. I've prepared a VMware virtual machine that exhibits the problem exactly. Download the VM at http://down.nlscan.com/misc/chj/winxp-svnhook-py-stdin-error.7z (link expected to be valid until Sep 2013). VMware Player 3.0(free) is sufficient to run that VM.
===============[WORKAROUND FOUND]===================
Very nice workaround provided by #nmenezes, with c:\Python27\python.exe D:\svntest\testhook.py %* in bat .
SVN is executing the script without an associated console.
So you won't see anything displayed on STDOUT.
Everything sent to STDERR is displayed as a message on SVN, if the script returns an error code different of 0.
This kind of script should run unattended, it is independent of input or output from the user.
You can try to pass the property value as an extra command line parameter.
To do so, change your .bat to:
#echo off
set /p NEWTEXT=
test.py %* %NEWTEXT%
exit /b %ERRORLEVEL%
And the .py to:
import os, sys
if __name__ == '__main__':
newtext = sys.argv[6]
sys.stderr.write('newtext is: %s\n'% newtext)
exit(2)
I read the batch STDIN to NEWTEXT variable and I pass it to your script as an extra command line parameter.
This solution does not work for multiple lines values. So, I tried again your original solutions and it worked fine.
svn propset svn:log --revprop -r 3 -F svn.txt
In this case, the property value is read from the svn.txt file, a text file with multiple lines. In this case, the option with set /p does not work, as we discussed in the comments. But the original script works.
For information, 5 properties are passed on the command line:
1 - repository
2 - revision number
3 - user
4 - property name
5 - operation (M in this case)
The property value is passed on the stdin of the batch script.
#Chen, I finally downloaded the image. The problem is solved when you change the hook batch to:
c:\python27\python.exe d:\svntest\testhook.py %*
exit %ERRORLEVEL%
It looks that the way your XP machine executes python directly is misconfigured.
Isn't it up to your batch file to direct the stdin it received into the script that it calls?
For reference: http://www.microsoft.com/resources/documentation/windows/xp/all/proddocs/en-us/redirection.mspx?mfr=true
Maybe you can just prefix the call to your script with the > symbol to have this happen?
> D:\svntest\testhook.py %*
exit /b %ERRORLEVEL%
It seems like if the batch file can read from stdin, then SVN is doing what it is supposed to and it is up to your batch file to make that available to the additional script that you call.
I have mysql dump command that I would like to run from from windows shell
or command prompt. I have used shell it does work.
d= 'BkSql_'+datetime.datetime.now().strftime("%Y-%m-%d")+".sql"
fn = dn+d
cmd="""mysqldump -u hapopdy -p > %s""" %fn
print cmd
Edit:::::::
The -p needs to be a raw input.
Using the subprocess module
import subprocess
subprocess.call(cmd)
If you're running a shell command add shell=True
subprocess.call(cmd, shell=True)
You should save the password in mysql's local configuration file for the user.(In Unix it's ~/.my.cnf) or you can give it on the command line with --password=MYPASSWORD.
Either way, the password will be visible to a large audience. In the .my.cnf case, it will be visible to anyone with read access to the file. In the second case, it will be visible to anyone who can get a process listing on the system, in addition to those who have read access to your script.