how can we automate IBM ACS 5250 session via Python/Java? [duplicate] - python

I need to login to IBM i System using Python without entering the username and password manually.
I used py3270 library but it is not able to detect the Emulator wc3270. The emulator I use has .hod extension and opens with IBM i Launcher.
Can anyone help me with this? what could be the possible solution for this?

os.system() is a blocking statement. That is, it blocks, or stops further Python code from being executed until whatever os.system() is doing has completed. This problem needs us to spawn a separate thread, so that the Windows process executing the ACS software runs at the same time the rest of the Python code runs. subprocess is one Python library that can handle this.
Here is some code that opens an ACS 5250 terminal window and pushes the user and password onto that window. There's no error checking, and there are some setup details that my system assumes about ACS which your system may not.
# the various print() statements are for looking behind the scenes
import sys
import time
import subprocess
from pywinauto.application import Application
import pywinauto.keyboard as keyboard
userid = sys.argv[1]
password = sys.argv[2]
print("Starting ACS")
cmd = r"C:\Users\Public\IBM\ClientSolutions\Start_Programs\Windows_x86-64\acslaunch_win-64.exe"
system = r'/system="your system name or IP goes here"'
# Popen requires the command to be separate from each of the parameters, so an array
result = subprocess.Popen([cmd, r"/plugin=5250",system], shell=True)
print(result)
# wait at least long enough for Windows to get past the splash screen
print("ACS starting - pausing")
time.sleep(5)
print("connecting to Windows process")
ACS = Application().connect(path=cmd)
print(ACS)
# debugging
windows = ACS.windows()
print(windows)
dialog = ACS['Signon to IBM i']
print(dialog)
print("sending keystrokes")
keyboard.send_keys(userid)
keyboard.send_keys("{TAB}")
keyboard.send_keys(password)
keyboard.send_keys("{ENTER}")
print('Done.')

Currently, I am facing the same issue. I was able to run the IBMi (ACS), however, once it run, my python script stop functioning as if the app is preventing the python from being running. In generally speaking, the app seems to not detecting the script.But once I closed the app, my python script continue to work.. I put some indication e.g timesleep, however as i mentioned earlier, it only continue to that line of code once IBM is closed. There will be few lines to be added to move the selection to 5250 and inject the credential.
*I tried with pyautogui, still facing the same issue. so now i tried pywinauto import keyboard .
#Variables
dir = sys.argv[1]
username = sys.argv[2]
password = sys.argv[3]
x = dir.split("\\")
print(x[-1])
command = "cd \ && cd Users/Public/Desktop && " + '"' + x[-1] + '"'
print(command)
os.system(command)
------ FROM THIS LINE OF CODE ONWARDS, IT STOPPED RUNNING ONCE IBM IS LAUNCHED ---
print('TIME START')
time.sleep(5)
print('TIME END')
keyboard.send_keys(username)
keyboard.send_keys(password)
keyboard.send_keys("{ENTER}")
print('Done.')
Appreciate your help to look into this matter. Thanks

Related

How can we automate login to IBM System using Python?

I need to login to IBM i System using Python without entering the username and password manually.
I used py3270 library but it is not able to detect the Emulator wc3270. The emulator I use has .hod extension and opens with IBM i Launcher.
Can anyone help me with this? what could be the possible solution for this?
os.system() is a blocking statement. That is, it blocks, or stops further Python code from being executed until whatever os.system() is doing has completed. This problem needs us to spawn a separate thread, so that the Windows process executing the ACS software runs at the same time the rest of the Python code runs. subprocess is one Python library that can handle this.
Here is some code that opens an ACS 5250 terminal window and pushes the user and password onto that window. There's no error checking, and there are some setup details that my system assumes about ACS which your system may not.
# the various print() statements are for looking behind the scenes
import sys
import time
import subprocess
from pywinauto.application import Application
import pywinauto.keyboard as keyboard
userid = sys.argv[1]
password = sys.argv[2]
print("Starting ACS")
cmd = r"C:\Users\Public\IBM\ClientSolutions\Start_Programs\Windows_x86-64\acslaunch_win-64.exe"
system = r'/system="your system name or IP goes here"'
# Popen requires the command to be separate from each of the parameters, so an array
result = subprocess.Popen([cmd, r"/plugin=5250",system], shell=True)
print(result)
# wait at least long enough for Windows to get past the splash screen
print("ACS starting - pausing")
time.sleep(5)
print("connecting to Windows process")
ACS = Application().connect(path=cmd)
print(ACS)
# debugging
windows = ACS.windows()
print(windows)
dialog = ACS['Signon to IBM i']
print(dialog)
print("sending keystrokes")
keyboard.send_keys(userid)
keyboard.send_keys("{TAB}")
keyboard.send_keys(password)
keyboard.send_keys("{ENTER}")
print('Done.')
Currently, I am facing the same issue. I was able to run the IBMi (ACS), however, once it run, my python script stop functioning as if the app is preventing the python from being running. In generally speaking, the app seems to not detecting the script.But once I closed the app, my python script continue to work.. I put some indication e.g timesleep, however as i mentioned earlier, it only continue to that line of code once IBM is closed. There will be few lines to be added to move the selection to 5250 and inject the credential.
*I tried with pyautogui, still facing the same issue. so now i tried pywinauto import keyboard .
#Variables
dir = sys.argv[1]
username = sys.argv[2]
password = sys.argv[3]
x = dir.split("\\")
print(x[-1])
command = "cd \ && cd Users/Public/Desktop && " + '"' + x[-1] + '"'
print(command)
os.system(command)
------ FROM THIS LINE OF CODE ONWARDS, IT STOPPED RUNNING ONCE IBM IS LAUNCHED ---
print('TIME START')
time.sleep(5)
print('TIME END')
keyboard.send_keys(username)
keyboard.send_keys(password)
keyboard.send_keys("{ENTER}")
print('Done.')
Appreciate your help to look into this matter. Thanks

How to tell a Python script to close after running

I'm a complete beginner in python... I wrote a simple script that pulls some data from a website and saves it to a text file, but after running the script it just sits there and doesn't "terminate". Since I'll be running it as a windows task I need it close on its own after running. Is there a way to tell python to close the terminal after the script finishes? I've looked everywhere and it seems that most people are trying to do the opposite, keep it open after the code runs.
Not sure if it matters but I'm just running the .py file, not in VS or PyCharm. Thanks in advance.
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
import time
from datetime import date
driver = webdriver.Chrome()
driver.get("MyURL")
time.sleep(11)
first = driver.find_element_by_xpath('/html/body/main/div[2]/div/div/div/div[2]/div[1]/div/div[2]/div[2]/div/ul/table/tbody/tr[3]/td[2]/div/span[1]')
second = driver.find_element_by_xpath('/html/body/main/div[2]/div/div/div/div[2]/div[1]/div/div[2]/div[2]/div/ul/table/tbody/tr[2]/td[2]/div/span[1]')
third = driver.find_element_by_xpath('/html/body/main/div[2]/div/div/div/div[2]/div[1]/div/div[2]/div[2]/div/ul/table/tbody/tr[1]/td[2]/div/span[1]')
first = first.text
second = second.text
third = third.text
print(first, second, third)
today = date.today()
today1 = today.strftime('%b %d %Y')
list = (today1, first, second, third)
print(list)
file = open('test.txt', 'a')
file.write(today1)
file.write(' ')
file.write(first)
file.write(' ')
file.write(second)
file.write(' ')
file.write(third)
file.write('\n')
file.close()
driver.close()
For 1. you need to send your running process to the background and remove the associated job from current shell.
Press Ctrl+Z and type bg to send the installation process to the backgroud
then type disown.
You can now close the terminal, the process will still be alive. You can open another terminal and check its process id with ps -aef
In my case the process id is 14426. Unfortunately there's no easy way to reattach it to another terminal (See How to attach terminal to detached process?) unless you used something based on screen.
For 2. You can use the following command:
while kill -0 14426 >/dev/null 2>&1; do sleep 5 ; done ; echo "ok"
It will print ok when the process is over from an other terminal. You can of course change this echo command with something more complex.
Source: BASH: launch background process and check when it ends
Okay, I found something that worked. I noticed that the chromedriver process was still running even after the line driver.close() executed. I went ahead and killed the process and the script closed immediately. I guess driver.close() closes the chrome window but didn't kill chromedriver so the script was hanging waiting for the process to quit. I replaced driver.close() with driver.quit() and now the script closes after running. Thanks everyone for the help!!

Is on Python 3 any library to relaunch the script?

I have some script in Python, which does some work. I want to re-run this script automatically. Also, I want to relaunch it on any crashes/freezes.
I can do something like this:
while True:
try:
main()
except Exception:
os.execv(sys.executable, ['python'] + sys.argv)
But, for unknown reason, this still crashes or freezes one time in few days. So I see crash, write "Python main.py" in cmd and it started, so I don't know why os.execv don't do this work by self. I guess it's because this code is part of this app. So, I prefer some script/app, which will control relaunch in external way. I hope it will be more stable.
So this script should work in this way:
Start any script
Check that process of this script is working, for example check some file time change and control it by process name|ID|etc.
When it dissapears from process list, launch it again
When file changed more than 5 minutes ago, stop process, wait few sec, launch it again.
In general: be cross-platform (Linux/Windows)
not important log all crashes.
I can do this by self (right now working on it), but I'm pretty sure something like this must already be done by somebody, I just can't find it in Google\Github.
UPDATE: added code from the #hansaplast answer to GitHub. Also added some changes to it: relauncher. Feel free to copy/use it.
As it needs to work both in windows and on linux I don't know a way to do that with standard tools, so here's a DIY solution:
from subprocess import Popen
import os
import time
# change into scripts directory
abspath = os.path.abspath(__file__)
dname = os.path.dirname(abspath)
os.chdir(dname)
while True:
p = Popen(['python', 'my_script.py', 'arg1', 'arg2'])
time.sleep(20) # give the program some time to write into logfile
while True:
if p.poll() != None:
print('crashed or regularly terminated')
break
file_age_in_s = time.time() - os.path.getmtime('output.log')
if file_age_in_s > 60:
print('frozen, killing process')
p.kill()
break
time.sleep(1)
print('restarting..')
Explanation:
time.sleep(20): give script 20 seconds to write into the log file
poll(): regularly check if script died (either crashed or regularly terminated, you can check the return value of poll() to differentiate that)
getmtime(): regularly check output.log and check if that was changed the past 60 seconds
time.sleep(1): between every check wait for 1s as otherwise it would eat up too many system resources
The script assumes that the check-script and the run-script are in the same directory. If that is not the case, change the lines beneath "change into scripts directory"
I personally like supervisor daemon, but it has two issues here:
It is only for unix systems
It restarts app only on crashes, not freezes.
But it has simple XML-RPC API, so It makes your job to write an freeze-watchdog app simplier. You could just start your process under supervisor and restart it via supervisor API when you see it freezes.
You could install it via apt install supervisor on ubuntu and write config like this:
[program:main]
user=vladimir
command=python3 /var/local/main/main.py
process_name=%(program_name)s
directory=/var/local/main
autostart=true
autorestart=true

Running Python Script at Startup to log mouse and keyboard activity in Linux

I'm quite confident many people before asked this question or at least a similar question. My problem is a little bit problematic but it's simple.
I've tried to run a Python script at startup with cron and by editing etc/rc.local file in Linux, but both ways failed to run my Python script.
My script logs the activity of the keyboard and the mouse using listener objects for both keyboard and mouse. I use a third-party package called pynput which depends on Xlib. My script edits a file that requires sudo access, so I must run my script with sudo.
You need to have a look at the script, so you know:
#!/usr/bin/env python
#backlight.py
from pynput.keyboard import Listener as KeyboardListener
from pynput.mouse import Listener as MouseListener
import time
STATUS = "" # Keyboard backlight ON/OFF status
turnOffSecs = 6 # Turn off keyboard backlight for x seconds of inactivity
# Keyboard brightness control file (change to your directory)
file_pth = "/sys/devices/platform/asus-nb-wmi/leds/asus::kbd_backlight/brightness"
def get_LEVEL():
"""return the current level of brightness of keyboard backlight"""
with open(file_pth, "r") as f:
brightness_level = f.read()[0]
return brightness_level
class Sec_timer:
"""
Sec_timer(until=None)
Create a timer that counts x number of seconds starting from 0
until arg can be used for reseting the timer:
*Example:
timer = Sec_imer(20)
while timer.elapsed < timer.until:
timer.count() # count a second
else:
timer.reset_timer() # reset timer on exit
"""
def __init__(self, until=None):
self.until = until
self.elapsed = 0
def count_sec(self):
"Count one second per-call"
time.sleep(1)
self.elapsed += 1
def reset_timer(self):
self.elapsed = 0
timer = Sec_timer(turnOffSecs) # Sec_timer(x) turn off keyboard backlight for x seconds of inactivity
# General event handler to reset timer
def reset_timer(*args):
global STATUS
timer.reset_timer()
if STATUS == "OFF":
# print(STATUS)
with open(file_pth, "w") as f:
f.write(current_brightnessLevel)
f.close()
STATUS="ON"
keyboard_listener = KeyboardListener(on_press=reset_timer,
on_release=(lambda *args: None))
mouse_listener = MouseListener(on_click=reset_timer,
on_scroll=reset_timer,
on_move=reset_timer)
keyboard_listener.start()
mouse_listener.start()
while True:
timer.count_sec()
if timer.elapsed > timer.until:
# print "current brightness:" + get_LEVEL()
if get_LEVEL() != "0":
with open(file_pth, "w") as f:
current_brightnessLevel = get_LEVEL()
f.write("0")
STATUS = "OFF"
This script logs the activity of the keyboard and the mouse, any keyboard or mouse activity will reset the timer. When x seconds passed and no keyboard or mouse activity took place, turn off the back light of the keyboard by writing "0" to the brightness folder. If any mouse or keyboard event takes place after the script turned off the back-light turn the keyboard brightness on according to the previous brightness level of the back-light.
Running the script using terminal, it works perfectly fine. But, automating the launch of this script is tricky; here's what I tried so far:
*Note, I've made the script file executable and backlight.py resides in /home/user:
1) In terminal:
$ xhost +
$ sudo ./backlight.py
Works fine!
2) Using `etc/rc.local I added:
xhost +
cd /home/user/
./backlight.py
Script didn't run after reboot
3) using etc/rc.local
$ sudo crontab -e
#reboot xhost +
#reboot /home/user/backlight.py
Didn't run after reboot
I had to execute xhost + because of a problem with Xlib. Using the last two ways didn't work. I'm guessing this is a programming problem and perhaps it has something to do with Xlib?!
I know this script is insane in terms of interfacing with keyboard LEDS and call it "bad script" if you will. Though I'm just trying to solve a driver problem using file input/output solution, because I don't have the appetite to delve into Linux driver details, at least not for now!
Well if it needs root and has to be run at startup, why not create a custom service?
If say you create a custom service, systemd can start it for you.
You can then start your service with sudo systemctl start yourservice
And you can make sure it runs at startup (as root) with sudo systemctl enable yourservice. It will start irrespective of the user.
I haven't personally done this before but it shouldn't be too difficult. It's basically just a file containing a description and an execute command, created in the directory /etc/systemd/system. A quick googling gave me this guide: https://blog.sdbarker.com/post/adding-custom-units-services-to-systemd-on-arch-linux/
Hope that helps.

subprocess can't successfully restart the targeted python file

I write a program my_test.py to get data from web and store to mysql.
But the program my_test.py collapses a lot (my bad programming skill...) and I try to monitor its status and restart it when it collapses.
I use subprocess modular with the following codes.
import subprocess
import time
p = subprocess.Popen(['python.exe', r'D:\my_test.py'], shell=True)
while True:
try:
stopped = p.poll()
except:
stopped = True
if stopped:
p = subprocess.Popen(['python.exe', r'D:\my_test.py'], shell=True)
time.sleep(60)
But when my_test.py collapses, a windows warning window jumps out to alert me that my_test.py is down and which action I will choose: stop, debug ...
Something like that.
And my_test.py seems frozen by the alert windows and the codes above can't restart it successfully.
Only when I manually close the window by choose 'close', it will restart again.
It there any solution to this problem such that my codes can successfully restart my_test.py when it breaks down?
Sorry for the inconvinience brought by my poor English and thank in advance for your kind advices.
There are two parts in your question:
what to do with the debug dialog. You could try this: How do I disable the 'Debug / Close Application' dialog on Windows Vista?
how to restart the script automatically
How to restart
The priority order:
fix my_test.py, to avoid crashing due to known issues
use a supervisor program to run your script such as upstart or supervisord -- they can restart it automatically if it crashes
write your own supervisor program with its own bugs that you have to maintain
It is best to limit yourself to options 1 and/or 2 if you can find an already-written supervisor program that works on Windows (upstart and supervisord do not work on Windows).
Your current supervisor script could be improved to avoid waiting a minute before restarting the program after it crashes if it has been running more than a minute already:
#!/usr/bin/env python3
import sys
import subprocess
import time
try:
from time import monotonic as timer
except ImportError:
from time import time as timer # time() can be set back
while True:
earliest_next_start = timer() + 60
subprocess.call([sys.executable, r'D:\my_test.py'])
while timer() < earliest_next_start:
time.sleep(max(0, earliest_next_start - timer()))

Categories