Python, ¿cómo ejecutar comandos en hosts remotos y mostrar resultados en GUI en tiempo real?

Sé que esta es una pregunta realmente abierta, pero soy nuevo en Python y estoy creando una aplicación web única para ofrecer a un equipo no técnico algunas capacidades de autoservicio. Este equipo tiene un montón de tareas repetitivas que transfieren a otro equipo que está simplemente pidiendo ser automatizado, como reiniciar algunos procesos en hosts remotos, registros de grep, limpiar archivos antiguos, implementar / reiniciar nuevas versiones de una aplicación, ponerse al día. ejecutando versiones, etc. Los usuarios harán clic en los botones y verán la salida en la GUI, NO ingresarán manualmente los comandos para ejecutar (sé que esto es peligroso). Cualquier tarea nueva será progtwigda y agregada a la aplicación por el equipo de soporte técnico.

Ahora, la única parte de la que no estoy seguro es cómo obtener (casi) la salida en tiempo real de los comandos a la GUI. He creado una aplicación muy similar en PHP en el pasado, y lo que hice fue vaciar la salida de los comandos remotos a una base de datos, y luego sondear la db con ajax y agregar una nueva salida. Fue bastante simple y funcionó muy bien, aunque la salida se volvería a hacer en trozos (tuve la salida escrita en la GUI línea por línea, por lo que parecía que era en tiempo real). ¿Hay una mejor manera de hacer esto? Estaba pensando en usar sockets web para enviar la salida del comando a la GUI. ¿Buena idea? ¿Mala idea? ¿Algo mejor con una biblioteca de python? También puedo usar nodejs, si eso marca alguna diferencia, pero soy nuevo en ambos idiomas (ya tengo una aplicación de flask Python simple que funciona como una API para unir algunas aplicaciones empresariales, no es un gran problema reescribir en nodo).

Esta es una pregunta amplia, pero te daré algunas pistas.

Buen ejemplo es LogIo . Una vez que esté dispuesto a ejecutar algunos comandos y luego enviar la salida a la GUI, usar Node.js se convierte en un enfoque natural. Esta aplicación puede contener algunos elementos:

  • la primera parte que ejecuta los comandos y cosecha la salida y la empuja a
  • la segunda parte que recibe la salida y la guarda en la base de datos / archivos. Después de guardar, esta parte está lanzando evento a
  • la tercera parte , que debe ser un servidor websocket, que manejará a los usuarios que están en línea y distribuirá eventos a
  • la cuarta parte, que sería una GUI con guiones preoperatorios que puede conectarse a través de websocket a la tercera parte, iniciar sesión en el usuario, recibir eventos y transmitirlos a otros elementos de la GUI.

Una vez que asumo que se siente más fuerte con PHP que con python, para usted, el enfoque más sencillo sería crear la segunda parte como un servicio de PHP para manejar la entrada (guardar la salida recolectada en la base de datos) y, digamos, usar el paquete UDP para la tercera parte del UDP que escucha. .

La primera parte sería la secuencia de comandos de Python para obtener simplemente la salida del comando y pasarla por alto a la segunda parte . Debería ser tan fácil de manejar como en el caso habitual de grep :

tail -f /var/log/apache2/access.log | /usr/share/bin/myharvester 

en algún momento del desarrollo, estará en demanda de pasar allí también el usuario o el identificador de tarea único como parámetro después de myharvester .

Difícil pero más fácil de lo que crees será crear una criptografía Node.js como parte tres . Como secuencia de comandos de una sola instancia, debería poder recibir entradas y omitirlas a los usuarios como eventos. Me he comprometido a cometer así antes:

 var config = {}; var app = require('http').createServer().listen(config.server.port); var io = require('socket.io').listen(app); var listenerDgram = require('dgram').createSocket('udp4'); listenerDgram.bind(config.listeners.udp.port); var sprintf = require('sprintf').sprintf; var users = []; app.on('error', function(er) { console.log(sprintf('[%s] [ERROR] HTTP Server at port %s has thrown %s', Date(), config.server.port, er.toString())); process.exit(); }); listenerDgram.on('error', function(er) { console.log(sprintf('[%s] [ERROR] UDP Listener at port %s has thrown %s', Date(), config.listeners.udp.port, er.toString())); process.exit(); }); listenerDgram.on('message', function(msg, rinfo) { // handling, let's say, JSONized msg from part two script, // buildinf a var frame and finally if(user) { // emit to single user based on what happened // inside this method users[user].emit('notification', frame); } else { // emit to all users io.emit('notification', frame); } }); io.sockets.on('connection', function(socket) { // handling user connection here and pushing users' sockets to // users aray. }); 

Este chatarra es un ejemplo básico de no tener lógica lo que necesitas. El script debería poder abrir la escucha UDP en un puerto determinado y escuchar a los usuarios que se ejecutan en él dentro de websockets. Honestamente, una vez que se vuelva bueno en Node.js, querrá arreglar la parte dos + la parte tres con él, lo que le quitará parte UDP cuando el recolector empujará la salida directamente al script, que mantiene el websocket dentro de él. Pero tiene el inconveniente de duplicar alguna lógica de otro back-end como CRM.

La última ( cuarta ) parte sería implementar una interfaz web con JavaScript en su interior, que conecte al usuario registrado actualmente al servidor de socket.

He utilizado un enfoque similar antes, y funciona en tiempo real, por lo que podemos mostrar a nuestros empleados del Centro de llamadas información sobre las llamadas entrantes antes de que el teléfono comience a sonar. Finalmente, las soluciones (sin contar la interfaz de CRM) se cierran en dos secuencias de comandos: parte de la API de CRM dedicada (donde ocurre toda la lógica) para manejar los eventos del Asterisk y el reenvío de eventos Node.js.