How can I find the Command Line of a Process with Python? - python

I tried to get the Command Line of a running Process with Python.
I managed to do it with Powershell but I need to get it with Python which is my Problem.
Working Powershell Code:
Get-CimInstance Win32_Process -Filter "name = 'process.exe'" | select CommandLine
I tried everything I found but still can't do it...
It would be very nice if someone could help me.

This is answered here: https://stackoverflow.com/a/20721781/18505766
import psutil
for process in psutil.process_iter():
cmdline = process.cmdline
if "main.py" in cmdline and "testarg" in cmdline:
# do something
EDIT: Sorry, actually this is a bit different.
But if you're on Windows, you can try the following:
import wmi
w=wmi.WMI()
name = "cmd.exe"
for process in w.Win32_Process():
if process.Name == name:
tmp1 = process.Commandline
tmp2 = tmp1.split(' ', 1)
args = tmp2[1]
break
print(args)
EDIT2: improved code. Important: only the first process' arguments found are stored in var 'args'!

Related

Python exe not deleting itself

I'm trying to create a python script to convert into exe which just deletes itself. When I run it as .py file it works. The code is this:
import os
os.remove(os.getcwd + "\\test.py")
I'm working in Windows that's why I'm using \\ and the file is obviously named test.py. But when I convert it into an exe file (I've tried both with py2exe and pyinstaller) it gives me access denied error. Does anyone know how to fix this?
PS: Yes, I've changed the name to test.exe if you're asking.
It won't be this simple.
1) When you are running the script actually it is the python.exe executing the statements and the script file (test.py) is free. In this way python.exe can delete the script.
2) When you convert convert your script to exe, it is the exe file itself executing, which means the file is 'busy', or said in other words - used by the process, and it cannot be deleted.
Find a way to start another process, which would delete the file after you exit the current process.
Edit(sample code):
import sys
import ctypes
import platform
import subprocess
def execute(command, async=False):
"""
if async=False Executes a shell command and waits until termination and
returns process exit code
if async=True Executes a shell command without waiting for its
termination and returns subprocess.Popen object
On Windows, does not create a console window.
"""
if async:
call = subprocess.Popen
else:
call = subprocess.call
if platform.system() == 'Windows':
# the following CREATE_NO_WINDOW flag runs the process without
# a console window
# it is ignored if the application is not a console application
return call(command, creationflags=0x08000000)
else:
return call(command)
def main():
ctypes.windll.user32.MessageBoxA(0, __file__, 'Show path', 0)
ctypes.windll.user32.MessageBoxA(0, sys.executable, 'sys.executable', 0)
with open(r'D:\delete_me.py', 'w') as f:
f.write('import os\n')
f.write('import time\n')
f.write('time.sleep(2)\n')
f.write('os.remove(r"{}")'.format(sys.executable))
execute(r'C:\Python27\python.exe D:\delete_me.py', async=True)
if __name__ == '__main__':
main()
And this was compiled with `pyinstaller.exe --onefile --windowed D:\self_delete.py
execute function is something we use to execute calls on both Linux and Windows and I just copied it. This is why the platform check is there.
You can use some .bat file with timeout instead of sleep or whatever else you want if you can't execute delete_me.py
What you can do is to use a VBScript to do this. What I have done is made this:
deleteFile is the location of the exe you want to delete. It doesnt matter if its running or not, If its running then it will first be terminated forcefully then deleted, then the VBScript will delete itself too. All this will happen without the console window opening to make it more convenient for the end user. The Python Code is listed below this code
deleteFile ="Install.exe"
Dim oShell : Set oShell = CreateObject("WScript.Shell")
oShell.Run "taskkill /f /im install.exe", 0, True
Set fso = CreateObject("Scripting.FileSystemObject")
If fso.FileExists(deleteFile) Then
Set fs = CreateObject("Scripting.Filesystemobject")
fs.DeleteFile(deleteFile)
Else
End If
Set oFso = CreateObject("Scripting.FileSystemObject") : oFso.DeleteFile Wscript.ScriptFullName, True
The Python Code:
Here you will have to change \Filename.extention to \Yourfilename.yourfilextension for ex. \example.exe
import os
fname = "Filename.extention"
path = os.getcwd() + "\\" + fname
delcode = f'''deleteFile ="{path}"
Dim oShell : Set oShell = CreateObject("WScript.Shell")
oShell.Run "taskkill /f /im install.exe", 0, True
Set fso = CreateObject("Scripting.FileSystemObject")
If fso.FileExists(deleteFile) Then
Set fs = CreateObject("Scripting.Filesystemobject")
fs.DeleteFile(deleteFile)
Else
End If
Set oFso = CreateObject("Scripting.FileSystemObject") : oFso.DeleteFile Wscript.ScriptFullName, True'''
f = open("C:\Windows\Temp\delete.vbs", "w")
f.write(delcode)
os.startfile("C:\Windows\Temp\delete.vbs")
The only think you need to do is to add the python code to a function, then change what I said above and just run the function. I have tested it myself and it worked perfectly so there should be no errors in the code
Edit: I know its very old thread but I just wanted to put my answer too since I felt it was easier than others + I was also finding an answer myself to this question so why not to help others too incase someone comes across the same question!

Script to capture everything on screen

So I have this python3 script that does a lot of automated testing for me, it takes roughly 20 minutes to run, and some user interaction is required. It also uses paramiko to ssh to a remote host for a separate test.
Eventually, I would like to hand this script over to the rest of my team however, it has one feature missing: evidence collection!
I need to capture everything that appears on the terminal to a file. I have been experimenting with the Linux command 'script'. However, I cannot find an automated method of starting script, and executing the script.
I have a command in /usr/bin/
script log_name;python3.5 /home/centos/scripts/test.py
When I run my command, it just stalls. Any help would be greatly appreciated!
Thanks :)
Is a redirection of the output to a file what you need ?
python3.5 /home/centos/scripts/test.py > output.log 2>&1
Or if you want to keep the output on the terminal AND save it into a file:
python3.5 /home/centos/scripts/test.py 2>&1 | tee output.log
I needed to do this, and ended up with a solution that combined pexpect and ttyrec.
ttyrec produces output files that can be played back with a few different player applications - I use TermTV and IPBT.
If memory serves, I had to use pexpect to launch ttyrec (as well as my test's other commands) because I was using Jenkins to schedule the execution of my test, and pexpect seemed to be the easiest way to get a working interactive shell in a Jenkins job.
In your situation you might be able to get away with using just ttyrec, and skip the pexpect step - try running ttyrec -e command as mentioned in the ttyrec docs.
Finally, on the topic of interactive shells, there's an alternative to pexpect named "empty" that I've had some success with too - see http://empty.sourceforge.net/. If you're running Ubuntu or Debian you can install empty with apt-get install empty-expect
I actually managed to do it in python3, took a lot of work, but here is the python solution:
def record_log(output):
try:
with open(LOG_RUN_OUTPUT, 'a') as file:
file.write(output)
except:
with open(LOG_RUN_OUTPUT, 'w') as file:
file.write(output)
def execute(cmd, store=True):
proc = Popen(cmd.encode("utf8"), shell=True, stdout=PIPE, stderr=PIPE)
output = "\n".join((out.decode()for out in proc.communicate()))
template = '''Command:\n====================\n%s\nResult:\n====================\n%s'''
output = template % (cmd, output)
print(output)
if store:
record_log(output)
return output
# SSH function
def ssh_connect(start_message, host_id, user_name, key, stage_commands):
print(start_message)
try:
ssh.connect(hostname=host_id, username=user_name, key_filename=key, timeout=120)
except:
print("Failed to connect to " + host_id)
for command in stage_commands:
try:
ssh_stdin, ssh_stdout, ssh_stderr = ssh.exec_command(command)
except:
input("Paused, because " + command + " failed to run.\n Please verify and press enter to continue.")
else:
template = '''Command:\n====================\n%s\nResult:\n====================\n%s'''
output = ssh_stderr.read() + ssh_stdout.read()
output = template % (command, output)
record_log(output)
print(output)

How can python wait for a batch SGE script finish execution?

I have a problem I'd like you to help me to solve.
I am working in Python and I want to do the following:
call an SGE batch script on a server
see if it works correctly
do something
What I do now is approx the following:
import subprocess
try:
tmp = subprocess.call(qsub ....)
if tmp != 0:
error_handler_1()
else:
correct_routine()
except:
error_handler_2()
My problem is that once the script is sent to SGE, my python script interpret it as a success and keeps working as if it finished.
Do you have any suggestion about how could I make the python code wait for the actual processing result of the SGE script ?
Ah, btw I tried using qrsh but I don't have permission to use it on the SGE
Thanks!
From your code you want the program to wait for job to finish and return code, right? If so, the qsub sync option is likely what you want:
http://gridscheduler.sourceforge.net/htmlman/htmlman1/qsub.html
Additional Answer for an easier processing:
By using the python drmaa module : link which allows a more complete processing with SGE.
A functioning code provided in the documentation is here: [provided you put a sleeper.sh script in the same directory]
please notice that the -b n option is needed to execute a .sh script, otherwise it expects a binary by default like explained here
import drmaa
import os
def main():
"""Submit a job.
Note, need file called sleeper.sh in current directory.
"""
s = drmaa.Session()
s.initialize()
print 'Creating job template'
jt = s.createJobTemplate()
jt.remoteCommand = os.getcwd()+'/sleeper.sh'
jt.args = ['42','Simon says:']
jt.joinFiles=False
jt.nativeSpecification ="-m abe -M mymail -q so-el6 -b n"
jobid = s.runJob(jt)
print 'Your job has been submitted with id ' + jobid
retval = s.wait(jobid, drmaa.Session.TIMEOUT_WAIT_FOREVER)
print('Job: {0} finished with status {1}'.format(retval.jobId, retval.hasExited))
print 'Cleaning up'
s.deleteJobTemplate(jt)
s.exit()
if __name__=='__main__':
main()

How to terminate process from Python using pid?

I'm trying to write some short script in python which would start another python code in subprocess if is not already started else terminate terminal & app (Linux).
So it looks like:
#!/usr/bin/python
from subprocess import Popen
text_file = open(".proc", "rb")
dat = text_file.read()
text_file.close()
def do(dat):
text_file = open(".proc", "w")
p = None
if dat == "x" :
p = Popen('python StripCore.py', shell=True)
text_file.write( str( p.pid ) )
else :
text_file.write( "x" )
p = # Assign process by pid / pid from int( dat )
p.terminate()
text_file.close()
do( dat )
Have problem of lacking knowledge to name proces by pid which app reads from file ".proc".
The other problem is that interpreter says that string named dat is not equal to "x" ??? What I've missed ?
Using the awesome psutil library it's pretty simple:
p = psutil.Process(pid)
p.terminate() #or p.kill()
If you don't want to install a new library, you can use the os module:
import os
import signal
os.kill(pid, signal.SIGTERM) #or signal.SIGKILL
See also the os.kill documentation.
If you are interested in starting the command python StripCore.py if it is not running, and killing it otherwise, you can use psutil to do this reliably.
Something like:
import psutil
from subprocess import Popen
for process in psutil.process_iter():
if process.cmdline() == ['python', 'StripCore.py']:
print('Process found. Terminating it.')
process.terminate()
break
else:
print('Process not found: starting it.')
Popen(['python', 'StripCore.py'])
Sample run:
$python test_strip.py #test_strip.py contains the code above
Process not found: starting it.
$python test_strip.py
Process found. Terminating it.
$python test_strip.py
Process not found: starting it.
$killall python
$python test_strip.py
Process not found: starting it.
$python test_strip.py
Process found. Terminating it.
$python test_strip.py
Process not found: starting it.
Note: In previous psutil versions cmdline was an attribute instead of a method.
I wanted to do the same thing as, but I wanted to do it in the one file.
So the logic would be:
if a script with my name is running, kill it, then exit
if a script with my name is not running, do stuff
I modified the answer by Bakuriu and came up with this:
from os import getpid
from sys import argv, exit
import psutil ## pip install psutil
myname = argv[0]
mypid = getpid()
for process in psutil.process_iter():
if process.pid != mypid:
for path in process.cmdline():
if myname in path:
print "process found"
process.terminate()
exit()
## your program starts here...
Running the script will do whatever the script does. Running another instance of the script will kill any existing instance of the script.
I use this to display a little PyGTK calendar widget which runs when I click the clock. If I click and the calendar is not up, the calendar displays. If the calendar is running and I click the clock, the calendar disappears.
So, not directly related but this is the first question that appears when you try to find how to terminate a process running from a specific folder using Python.
It also answers the question in a way(even though it is an old one with lots of answers).
While creating a faster way to scrape some government sites for data I had an issue where if any of the processes in the pool got stuck they would be skipped but still take up memory from my computer. This is the solution I reached for killing them, if anyone knows a better way to do it please let me know!
import pandas as pd
import wmi
from re import escape
import os
def kill_process(kill_path, execs):
f = wmi.WMI()
esc = escape(kill_path)
temp = {'id':[], 'path':[], 'name':[]}
for process in f.Win32_Process():
temp['id'].append(process.ProcessId)
temp['path'].append(process.ExecutablePath)
temp['name'].append(process.Name)
temp = pd.DataFrame(temp)
temp = temp.dropna(subset=['path']).reset_index().drop(columns=['index'])
temp = temp.loc[temp['path'].str.contains(esc)].loc[temp.name.isin(execs)].reset_index().drop(columns=['index'])
[os.system('taskkill /PID {} /f'.format(t)) for t in temp['id']]

How to run an AppleScript from within a Python script?

How to run an AppleScript from within a Python script?
The questions says it all..
(On a Mac obviously)
this nice article suggests the simple solution
cmd = """osascript -e 'tell app "Finder" to sleep'"""
def stupidtrick():
os.system(cmd)
though today you'd use the subprocess module instead of os.system, of course.
Be sure to also check page 2 of the article for many more info and options, including appscript.
A subprocess version which allows running an original apple script as-is, without having to escape quotes and other characters which can be tricky. It is a simplified version of the script found here which also does parametrization and proper escaping (Python 2.x).
import subprocess
script = '''tell application "System Events"
activate
display dialog "Hello Cocoa!" with title "Sample Cocoa Dialog" default button 2
end tell
'''
proc = subprocess.Popen(['osascript', '-'],
stdin=subprocess.PIPE,
stdout=subprocess.PIPE)
stdout_output = proc.communicate(script)[0]
print stdout_output
NOTE: If you need to execute more than one script with the same Popen instance then you'll need to write explicitly with proc.stdin.write(script) and read with proc.stdout.read() because communicate() will close the input and output streams.
I got the Output folks... Here it's following:
import subprocess
import sys
for i in range(int(sys.argv[1])):
ip = str(sys.argv[2])
username = str(sys.argv[3])
pwd = str(sys.argv[4])
script = '''tell application "Terminal"
activate
do script with command "cd Desktop && python test_switch.py {ip} {username} {pwd}"
delay 15
end tell
'''
proc = subprocess.Popen(['osascript', '-'],
stdin=subprocess.PIPE,
stdout=subprocess.PIPE)
stdout_output = proc.communicate(script.format(ip=ip, username=username, pwd=pwd))[0]
I was pretty frustrated at the lack of detail in Apple's own documentation regarding how to do this AND to also pass in arguments. I had to send the desired arg (in this case a zoom id) as a string otherwise the argument didn't come through to the applescript app
Here's my code running from python:
f = script if os.path.exists(script) else _tempfile()
if not os.path.exists(script):
open(f,'w').write(script)
args = ["osascript", f, str(zoom_id)]
kwargs = {'stdout':open(os.devnull, 'wb'),'stderr':open(os.devnull, 'wb')}
#kwargs.update(params)
proc = subprocess.Popen(args,**kwargs)
and here is my applescript:
on run argv
set zoom_id to 0
zoom_id = item 1 in argv
tell application "zoom.us"
--do stuff
end tell
end run

Categories

Resources