Send strings using python to /dev/tty - python

I have embedded system which runs on linux. I need to send some strings from this system using python script to other device, which is visible as USB serial COM port. Both devices connected to the same PC and are visible as serial COM ports. The data lines is physically connected between the devices.
When I write to the terminal this line
echo Hello! > /dev/ttyS1
I am successfully receiving the message on another COM port (terminal). How I can do same transmission using python? I saw that is used subprocess module for this task, and I think if I could fit it successfully, I would just stay with it, because I don't need to install a third party libraries on a low resource embedded system.
Now what I was trying to do using this module, F.e. when I tried to run ls -l command using subprocess, I get the correct output in the open embedded system terminal:
import subprocess
subprocess.call(["ls", "-l"])
When an Echo command is launched
import subprocess
subprocess.call(["echo", "Hello!"])
print("Executed")
but how can I use echo Hello! > /dev/ttyS1 command in this python script? I tried to implement it analogously but not very successful.

Try this:
proc = subprocess.Popen('echo Hello! > /dev/ttyS1', shell=True, stdout=subprocess.PIPE)
print(proc.communicate())

Related

Running command using Plink through Python and serial port?

I can open a new cmd window and connect with plink and serial port through Python.
import os
import subprocess
os.system("start cmd /k plink.exe -serial COM4 -sercfg 115200,8,n,1,N")
Still good here, but when I want to run ifconfig, it didn't work.
os.system("ifconfig")
First, consider using native Python serial connection implementation, like pySerial, instead of running a console application (plink).
See Full examples of using pySerial package.
Anyway if you run a Windows batch file that does what your Python code, it won't do what you want either:
start cmd /k plink.exe -serial COM4 -sercfg 115200,8,n,1,N
ifconfig
The ifconfig is not a top-level command. It's something that needs to be executed by Plink.
You have to feed the command to the plink standard input, see:
Execute a command on device over serial connection with Plink

Remote shutdown not working in Python

I'm trying to write up a small script using Python 2.7.7 that would ping an IP address and determine whether that PC is turned on or off, and change the power state of that system accordingly. I'm relying heavily on the Python modules subprocess and wakeonlan. I am not having any issues pinging or using WOL, but the shutdown functionality is behaving in a very strange way.
Using the command shutdown -s -t 0 /m \\XXX.XXX.X.X from the command prompt works fine, as well as the following from the Python interactive shell in cmd:
import subprocess
ip = 'XXX.XXX.X.X' # use for example
subprocess.call('shutdown -s -t 0 /m \\\\%s' % ip)
But running the same command in from a Python script is returning this error:
XXX.XXX.X.X: The entered computer name is not valid or remote shutdown is not supported on the target computer. Check the name and then try again or contact your system administrator.(53)
Are there any background behaviors that I'm not thinking about? Perhaps something to do with the subprocess module? Thanks in advance!

Calling a a remote interactive python script from a bash script: Input request lag

I wrote a bash script that at one point automates the installation of some software on a remote host, like so:
ssh user#remotehost "<path>/install-script"
Where install-script is a bash script. That bash script at some point calls another bash script, which at some point calls an interactive python script, which then uses python's raw_input() function to gather user input.
When I run the install script normally (from a bash shell), it prompts for and accepts input perfectly fine. However, when the above piece of code from my script runs, I get no prompt until after I type the input.
The only script I really have control over is my automation script.
I have read this question: "Python - how can I read stdin from shell, and send stdout to shell and file." However, I have no problem running in a normal bash shell, only via a remote command over ssh.
Can this issue be fixed from within my script (and if so, how?), or would I have to modify the python script?
UPDATE
To clarify, the input prompts I am referring to are the prompts from the python script. I am not entering a password for ssh (the remote host has my public key in it's authorized_keys file).
UPDATE
For further clarification, my script (bash) is calling the install script (bash) that calls another bash script that finally calls the python script, which prompts for user input.
i.e. bash -> bash -> bash -> python
ssh user#remotehost "<path>/install-script"
When you run ssh and specify a command to invoke on the remote system, by default ssh will not allocate a PTY (pseudo-TTY) for the remote session. This means that you will communicate with the remote process through a set of pipes rather than a TTY.
When writing to a pipe, unix programs will typically buffer their write operations. You won't see output written to a pipe until the process writing to the pipe flushes its buffer, or when it exits--because buffered output is normally flushed on exit. Beyond that, a process can detect whether it's writing to a file, pipe, or tty, and it may adjust its behavior. For example, a shell like bash won't print command prompts when reading commands from a pipe.
You can force ssh to request a TTY for the session using the -t option:
ssh -tt user#remotehost "<path>/install-script"
Refer to the ssh man page for details.

Error when opening interactive ssh shell from python

I am trying to open an interactive ssh shell through fabric.
Requirements:
Use fabrics hosts in the connection string to remote
Open fully interactive shell in current terminal
Works on osx and ubuntu
No need for data transfer between fabric/python and remote. So fabric task can end in background.
So far:
fabfile.py:
def test_ssh():
from subprocess import Popen
Popen('ssh user#1.2.3.4 -i "bla.pem"', shell=True)
In terminal:
localprompt$ fab test_ssh
localprompt$ tcsetattr: Input/output error
[remote ubuntu welcome here]
remoteprompt$ |
Then if I try to input a command on the remote prompt it is executed locally and I drop back to the local prompt.
Does anyone know a solution?
Note: I am aware of fabrics open_shell, but this does not work for me since the stdout lags behind, rendering this unusable.
A slight modification does the trick:
def test_ssh():
from subprocess import call
call('ssh user#1.2.3.4 -i "bla.pem"', shell=True)
As the answer to this question suggests the error suggests the error comes from the inability of ssh to connect to the stdin/out of a process in the background.
With call the fabric task does not end in the background, but I am fine with that as long as as it is not interfering with my stdin/out.

Telnet Server ubuntu - password stream

I am trying to create a Telnet Server using Python on Ubuntu 12.04. In order to be able to execute commands as a different user, I need to use the su command, which then prompts for the password. Now, I know that the prompt is sent to the STDERR stream, but I have no idea which stream I am supposed to send the password to. If I try to send it via STDIN, I get the error: su: must be run from a terminal. How do I proceed?
If you really want to use system's su program, you will need to create a terminal pair, see man 7 pty, in python that's pty.openpty call that returns you a pair of file descriptors, one for you and one for su. Then you have to fork, in the child process change stdin/out/err to slave fd and exec su. In the parent process you send data to and receive data from master fd. Linux kernel connects those together.
Alternatively you could perhaps emulate su instead?

Categories