How to include python script inside a NodeJS file? - python

Good day everyone,
Through recommendation of this community, I have install shelljs such as npm install shelljs --save into my app folder.
Now I am working out on how to implement it in my nodejs file.
Below is my nodejs file
var express = require('express');
var router = express.Router();
var COMPORT = 5;
var command = 'option1';
Below this i would like to include my python script
import serial
ser = serial.Serial()
ser.baudrate = 38400 #Suggested rate in Southco documentation, both locks and program MUST be at same rate
// COMPORT is a variable that stores an integer such as 6
ser.port = "COM{}".format(COMPORT)
ser.timeout = 10
ser.open()
#call the serial_connection() function
ser.write(("%s\r\n"%command).encode('ascii'))
Hence, my question is how do you include this python script with the variables defined in nodejs included in the script in the same file as the nodejs.
This app that runs on nodejs will be package as an executable desktop app via electron.

I think it is the easiest way to run python script as child process.
const childProcess = require('child_process'),
cmd = './script.py --opt=' + anyValueToPass;
childProcess.exec(cmd, function(err, stdout, stderr) {
// command output is in stdout
});
Read more about child process at: Execute a command line binary with Node.js
In this way, you ned to care for command injection vulnerability.

Related

Command output is corrupted when executed using Python Paramiko exec_command

I'm a software tester, trying to verify that the log on a remote QNX (a BSD variant) machine will contain the correct entries after specific actions are taken. I am able to list the contents of the directory in which the log resides, and use that information in the command to read (really want to use tail -n XX <file>) the file. So far, I always get a "(No such file or directory)" when trying to read the file.
We are using Froglogic Squish for automated testing, because the Windows UI (that interacts with the server piece on QNX) is built using Qt extensions for standard Windows elements. Squish uses Python 2.7, so I am using Python 2.7.
I am using paramiko for the SSH connection to the QNX server. This has worked great for sending commands to the simulator piece that also runs on the QNX server.
So, here's the code. Some descriptive names have been changed to avoid upsetting my employer.
import sys
import time
import select
sys.path.append(r"C:\Python27\Lib\site-packages")
sys.path.append(r"C:\Python27\Lib\site-packages\pip\_vendor")
import paramiko
# Import SSH configuration variables
ssh_host = 'vvv.xxx.yyy.zzz'
thelog_dir = "/logs/the/"
ssh_user = 'un'
ssh_pw = 'pw'
def execute_Command(fullCmd):
outptLines = []
#
# Try to connect to the host.
# Retry a few times if it fails.
#
i = 1
while True:
try:
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(ssh_host, 22, ssh_user, ssh_pw)
break
except paramiko.AuthenticationException:
log ("Authentication failed when connecting to %s" % ssh_host)
return 1
except:
log ("Could not SSH to %s, waiting for it to start" % ssh_host)
i += 1
time.sleep(2)
# If we could not connect within time limit
if i == 30:
log ("Could not connect to %s. Giving up" % ssh_host)
return 1
# Send the command (non-blocking?)
stdin, stdout, stderr = ssh.exec_command(fullCmd, get_pty=True)
for line in iter(stdout.readline, ""):
outptLines.append(line)
#
# Disconnect from the host
#
ssh.close()
return outptLines
def get_Latest_Log():
fullCmd = "ls -1 %s | grep the_2" %thelog_dir
files = execute_Command(fullCmd)
theFile = files[-1]
return theFile
def main():
numLines = 20
theLog = get_Latest_Log()
print("\n\nThe latest log is %s\n\n" %theLog)
fullCmd = "cd /logs/the; tail -n 20 /logs/the/%s" %theLog
#fullCmd = "tail -n 20 /logs/the/%s" %theLog
print fullCmd
logLines = execute_Command(fullCmd)
for line in logLines:
print line
if __name__ == "__main__":
# execute only if run as a script
main()
I have tried to read the file using both tail and cat. I have also tried to get and open the file using Paramiko's SFTP client.
In all cases, the response of trying to read the file fails -- despite the fact that listing the contents of the directory works fine. (?!) And BTW, the log file is supposed to be readable by 'world'. Permissions are -rw-rw-r--.
The output I get is:
"C:\Users\xsat086\Documents\paramikoTest>python SSH_THE_MsgChk.py
The latest log is the_20210628_115455_205.log
cd /logs/the; tail -n 20 /logs/the/the_20210628_115455_205.log
(No such file or directory)the/the_20210628_115455_205.log"
The file name is correct. If I copy and paste the tail command into an interactive SSH session with the QNX server, it works fine.
Is it something to do with the 'non-interactive' nature of this method of sending commands? I read that some implementations of SSH are built upon a command that offers a very limited environment. I don't see how that would impact this tail command.
Or am I doing something stupid in this code?
I cannot really explain completely, why you get the results you get.
But in general a corrupted output is a result of enabling and not handling terminal emulation. You enable the terminal emulation using get_pty=True. Remove it. You should not use the terminal emulation, when automating command execution.
Related question:
Is there a simple way to get rid of junk values that come when you SSH using Python's Paramiko library and fetch output from CLI of a remote machine?

Reloading vs. restarting uWSGI to activate code changes

After reading the uWSGI's documentation on reloading, my understanding was that, for an app that uses lazy-apps, writing w to uWSGI's master FIFO should trigger a restart of all workers (and hence activate changes in the Python code).
However, that doesn't seem to work for me. I need to restart the systemd service (systemctl restart myservice) for code changes to take effect. Am I misunderstanding the documentation, or is there an issue with my setup?
My myservice.service file looks like this:
...
ExecStart=/usr/lib/myservice/virtualenv/bin/uwsgi --ini /etc/myservice/uwsgi.ini
ExecReload=/bin/echo 'w' > /run/myservice/masterfifo
ExecStop=/bin/kill -INT $MAINPID
...
In particular, systemctl reload myservice should write w to the master FIFO. I can see from the logs in systemctl status myservice that the reload was executed, but the responses to HTTP requests tell me that the old code is still active.
My /etc/myservice/uwsgi.ini like this:
[uwsgi]
processes = 16
procname-master = myservice
master-fifo = /run/myservice/masterfifo
touch-chain-reload
listen = 128
thunder-lock
reload-on-as = 4096
limit-as = 8192
max-requests = 2000
; termination options
vacuum
die-on-term
; application
chdir = /usr/lib/myservice
virtualenv = /usr/lib/myservice/virtualenv
module = myservice.uwsgi
callable = app
master
need-app
enable-threads
lazy = True
lazy-apps = True
; logging
logto = /var/log/myservice/uwsgi.log
log-maxsize = 5242880
logdate = [%%Y/%%m/%%d %%H:%%M:%%S]
disable-logging
; stats server
stats-server = :8201
memory-report
; unix socket config (nginx->uwsgi)
socket = /run/myservice/myservice.sock
chown-socket = api
chmod-socket = 660
I'm running version 2.0.19.1 of uWSGI.
All I know about uWSGI is that it exists, but I noticed a mistake here:
ExecReload=/bin/echo 'w' > /run/myservice/masterfifo
The man page explains the problem:
This syntax is inspired by shell syntax, but only the meta-characters
and expansions described in the following paragraphs are understood,
and the expansion of variables is different. Specifically, redirection
using "<", "<<", ">", and ">>", pipes using "|", running programs in
the background using "&", and other elements of shell syntax are not
supported.
In other words, no redirection is taking place and echo will simply receive 3 arguments to print: char w, char > and the string /run/myservice/masterfifo.
Try this instead:
ExecReload=/bin/sh -c '/bin/echo w > /run/myservice/masterfifo'

python-serial OSError: [Errno 11] Resource temporarily unavailable

I am using Arduino Nano to serial communicated with ODROID (single-board computer installed Ubuntu 14.04).
The Arduino code:
void setup() {
Serial.begin(9600); // set the baud rate
Serial.println("Ready"); // print "Ready" once
}
void loop() {
char inByte = ' ';
if(Serial.available()){ // only send data back if data has been sent
char inByte = Serial.read(); // read the incoming data
Serial.println(inByte);
}
delay(100); // delay for 1/10 of a second
}
The Python code in ODROID:
#!/usr/bin/env python
from time import sleep
import serial
ser = serial.Serial('/dev/LIDAR', 9600, timeout=1) # Establish the connection on a specific port
sleep(1)
print "Arduino is initialized"
counter = 32 # Below 32 everything in ASCII is gibberish
while True:
if (ser.inWaiting()>0):
counter +=1
ser.write(str(chr(counter))) # Convert the decimal number to ASCII then send it to the Arduino
print ser.readline() # Read the newest output from the Arduino
sleep(.1) # Delay for one tenth of a second
if counter == 255:
counter = 32
ser.close
Traceback(most recent last):
File "./serial_test1.py", line 16, in <module>
print ser.readline() # Read the newest output from the Arduino
File "/usr/lib/python2.7/dis-package/serial/serialposix.py", line 43, in read
buf = os.read(self.fd, size-len(read))
OSError: [Errno 11]Resource temporarily unavailable
Then I had this issue after print some values, I know this problem maybe no data in available at current time. But how can I figure out this issue. Thanks for your help.
I don't know if this will work for ODROID, but I found a post about similar problem with Raspberry PI. In that post one of the answers redirected to this link
There it says the problems is caused by Raspberry Pi serial port, which is used by default to use the system console which conflicts when you try to use it for your own purposes
To disable the serial por for console you must edit the file /etc/inittab and comment the line T0:23:respawn:/sbin/getty -L ttyAMA0 115200 vt100 (You comment it with a # at the begining of the line, like in python). You must reboot the ODROID and it should work
I suggest you to read the answer I linked cause it explains a bit more about how can you substitute the serial port to access the command line (It suggests using ssh) and another thing is that Raspberry PI (And assume ODROID works similar) sends at boot time a message through serial port that will be received by the Arduino. You can remove that message and it's explained there
Hope this helps you
You are receiving this error since your serial device is being used by os itself. You should stop os to use this device.
Serial getty is now a service and you should stop and/or disable it:
sudo systemctl stop serial-getty#ttyAMA0.service
sudo systemctl disable serial-getty#ttyAMA0.service
Note that my native serial device id is ttyAMA0.
to permanently disable serial service, use
sudo systemctl mask serial-getty#ttyAMA0.service
in this case serial service will not start even on reboot.

How to list current directory files through socket API?

So right now I have a simple FTP system to transfer files.
But I am confused about how I would run commands on the server machine from a client machine.
How would I open a terminal on the server machine from my client machine to use commands such as ls or mkdir or cd? Or can I do this straight from Socket Programming
You could use the python module subprocess. (https://pymotw.com/2/subprocess/)
For example, assuming you have a client/server 'dialogue' set up using sockets, you could do something like this:
client.py
# assume 's' is your socket already connected to the server
# prompt the user for a command to send
cmd = raw_input("user > ")
s.send(cmd) # send your command to the server
# let's say you input 'ls -la'
You could put the above code inside a loop that only breaks when you enter 'quit' or something, to continually send and receive commands. You would need a loop or something similar on the server side too, to continually accept and return the output from your commands. You could also use threads.
server.py
# on the server side do this
# s is again your socket bound to a port
# but we're on the server side this time!
from subprocess import Popen, PIPE
cmd = s.recv(1024)
# cmd now has 'ls -la' assigned to it
# parse it a bit
cmd = cmd.split() # to get ['ls', '-la']
# now we execute the command on the server with subprocess
p = Popen(cmd, stdout=PIPE)
result = p.communicate()
# result is, in this case, the listing of files in the current directory
s.send(result[0]) # result[0] should be a str
# you now make sure to receive your result on the client
Note: I think a newer version is subprocess32, but all methods are the same as far as I remember.

Read / Write simultaneously python subprocess.Popen

I have a simple C program which works the following way:
Ask for input
Print it
Ask another input
Print again
Now iam using python to call this program.
import subprocess
sobj = subprocess.Popen("./cprog", stdin = subprocess.PIPE, stdout = subprocess.PIPE)
sobj.stdin.write("2 3\n")
sobj.stdin.close()
sobj.stdout.read()
This works fine. Similarly with communicate its working fine.
But when I try to do something like this it won't work
sobj = subprocess.Popen("./cprog", stdin = subprocess.PIPE, stdout = subprocess.PIPE)
sobj.stdout.readline()
sobj.stdin.write("2 3\n")
sobj.stdin.close()
sobj.stdout.read()
Here are the few things:
1. I saw pexpect but I think we should give what program asks in advance.
2. Can I reopen closed subprocess pipe ?
Iam using the above script as CGI and I don't know why but subprocess.call won't work in that. Can anyone explain why?
EDIT:
Iam doing a web based project where users write code in either C, C++ or JAVA and execute them on browser. So first I thought of using PHP for it but I couldn't find a way to call programs and run them interactively. Then I saw python subprocess module. Everything was working fine in interpreter when I was using subprocess.call. But the same python program when saved it as .cgi and opened it in browser it didn't work. Then I started looking at subprocess.popen. But with this I need to give all the inputs in beginning and then run the code. What I want to do is run an interactive session in browser.
EDIT 2:
So what I want is user runs program in browser and enters input in textbox provided whenever needed and that input is redirected to stdin of subprocess and output based on it.
EDIT 3: cprog.c
#include <stdio.h>
int main() {
int x;
printf("Enter value of x: \n");
scanf("%d", &x);
printf("Value of x: %d\n", x);
return 0;
}
I'm assuming your C application displays a prompt and expects the user to enter their input on the same line, and that in your readline() call above you're trying to get the prompt.
If this is the case, readline() will block forever because it's waiting for a newline character and never seeing it. If you convert this call to a simple read(X) (where X is a number of bytes to read in one go) then you'll probably have better luck, although you should cope with partial input (i.e. loop around collecting input until you've seen the whole prompt). The only other issue you might see is if the C application isn't flushing the output before prompting the user, but I'd expect you to see that problem in the interactive session as well if that were the case.
When running under the context of a webserver like Apache then it's generally a bad idea to use things like subprocess as they involve forking additional processes and that's often quite a tricky thing to manage. This is because the fork process duplicates much of the state of the parent and sometimes this can cause issues. I'm not saying it won't work, I'm just saying you can make some subtle problems for yourself if you're not careful, and it wouldn't surprise me if that's why you're having trouble using subprocess.
To give any more helpful advice, though, you'd need to describe exactly the error you see when you call subprocess. For example, there's quite likely an exception being thrown which will probably be in your webserver logs - reproducing that here would be a good start.
When I run C program directly through terminal its working fine. But when I run the same program with 2nd code i provided above nothing prints.
The reason you don't see any output is that C stdio uses block-buffering when the program is run in non-interactive mode. See my answer that demonstrate several solutions: pty, stdbuf, pexpect. If you can change the C code then you could also fflush the output explicitly or make it unbuffered.
If you can provide all input at once and the output is bounded then you could use .communicate():
from subprocess import Popen, PIPE
p = Popen(["./cprog"], stdin=PIPE, stdout=PIPE, stderr=PIPE,
universal_newlines=True)
out, err = p.communicate("2\n")
So what I want is user runs program in browser and enters input in textbox provided whenever needed and that input is redirected to stdin of subprocess and output based on it.
Based on ws-cli example:
#!/usr/bin/python
"""WebSocket CLI interface.
Install: pip install twisted txws
Run: twistd -ny wscli.py
Visit http://localhost:8080/
"""
import sys
from twisted.application import strports # pip install twisted
from twisted.application import service
from twisted.internet import protocol
from twisted.python import log
from twisted.web.resource import Resource
from twisted.web.server import Site
from twisted.web.static import File
from txws import WebSocketFactory # pip install txws
class Protocol(protocol.Protocol):
def connectionMade(self):
from twisted.internet import reactor
log.msg("launch a new process on each new connection")
self.pp = ProcessProtocol()
self.pp.factory = self
reactor.spawnProcess(self.pp, command, command_args)
def dataReceived(self, data):
log.msg("redirect received data to process' stdin: %r" % data)
self.pp.transport.write(data)
def connectionLost(self, reason):
self.pp.transport.loseConnection()
def _send(self, data):
self.transport.write(data) # send back
class ProcessProtocol(protocol.ProcessProtocol):
def connectionMade(self):
log.msg("connectionMade")
def outReceived(self, data):
log.msg("send stdout back %r" % data)
self._sendback(data)
def errReceived(self, data):
log.msg("send stderr back %r" % data)
self._sendback(data)
def processExited(self, reason):
log.msg("processExited")
self._sendback('program exited')
def processEnded(self, reason):
log.msg("processEnded")
def _sendback(self, data):
self.factory._send(data)
command = './cprog'
command_args = [command]
application = service.Application("ws-cli")
echofactory = protocol.Factory()
echofactory.protocol = Protocol
strports.service("tcp:8076:interface=127.0.0.1",
WebSocketFactory(echofactory)).setServiceParent(application)
resource = Resource()
resource.putChild('', File('index.html'))
strports.service("tcp:8080:interface=127.0.0.1",
Site(resource)).setServiceParent(application)
where index.html:
<!doctype html>
<title>Send input to subprocess using websocket and echo the response</title>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.0/jquery.min.js">
</script>
<script>
// send keys to websocket and echo the response
$(document).ready(function() {
// create websocket
if (! ("WebSocket" in window)) WebSocket = MozWebSocket; // firefox
var socket = new WebSocket("ws://localhost:8076");
// open the socket
socket.onopen = function(event) {
// show server response
socket.onmessage = function(e) {
$("#output").text(e.data);
}
// sent input
$("#entry").keyup(function (e) {
socket.send($("#entry").attr("value")+"\n");
});
}
});
</script>
<pre id=output>Here you should see the output from the command</pre>
<input type=text id=entry value="123">
And cprog.c:
#include <stdio.h>
int main() {
int x = -1;
setbuf(stdout, NULL); // make stdout unbuffered
while (1) {
printf("Enter value of x: \n");
if (scanf("%d", &x) != 1)
return 1;
printf("Value of x: %d\n", x);
}
return 0;
}

Categories

Resources