Имеется два скрипта.
Первый terminal.py - скрипт на Python3 и Tkinter. В нем создается окошко xterm, а под ним поле ввода команды и кнопка исполнения.
Второй input.sh - это демонстрационный bash-скрипт с командой read, чтобы продемонстрировать проблему.
Итак, запускается terminal.py. В области xterm можно напрямую вводить команды, и они исполняются. И если в нем запустить ./input.sh, то ввод работает без проблем, скрипт выполняется как положено.
Если же запустить команду ./input.sh в нижнем поле ввода окошка terminal.py и отправить ее на исполнение (все потоки 0, 1, 2 будут направлены в tty, где запущен xterm), то ввод read будет «проглатывать» символы. Хорошо если появится 1 из 10. И кнопку Enter в конце ввода сложно нажать. А если она все-таки нажмется, то окажется, что происходил не ввод текстовых данных через read, а происходил ввод bash-команды, которая, естественно, не выполнится и будет ошибка:
sh: 234: команда не найдена
В общем, не могу разобраться, можно ли что-нибудь в этой ситуации сделать, чтобы ввод read не терялся и работал правильно.
Сами скрипты даны ниже:
terminal.py
#!/usr/bin/python3
from tkinter import *
import os
import re
ttyDevice=""
def escapeString(s) :
result = re.sub(r'([ \"\'\|\<\>])', r'\\\1', s)
return result
def send_entry_to_terminal(*args) :
# Параметр *args необходим из-за того, что данная функция
# может быть вызвана без параметра (из кнопки)
# или с одним параметром (из поля ввода)
tty=ttyDevice
print('tty: '+tty)
command=commandEntry.get()
print('Command: '+command)
# Вывод в терминал строки команды, которая будет выполняться
cmdLine="echo %s <%s >%s 2> %s" % (escapeString(command), tty, tty, tty)
print('Echo line:')
print(cmdLine)
os.system(cmdLine)
# Выполнение команды в терминале
cmdLine="(%s) <%s >%s 2> %s" % (command, tty, tty, tty)
print('Command line:')
print(cmdLine)
os.system(cmdLine)
root = Tk()
# Место для вставки терминала
termFrame = Frame(root, height=700, width=1000)
termFrame.pack(fill=BOTH, expand=YES)
wid = termFrame.winfo_id()
print("Terminal window id: "+str(wid))
# Панель для ввода отправляемой команды
panelFrame=Frame(root)
Label(panelFrame, text="Command:").pack(side=LEFT)
commandEntry = Entry(panelFrame)
commandEntry.insert(0, "ls -l")
commandEntry.pack(side=LEFT,fill=X,expand=1)
commandEntry.bind("<Return>", send_entry_to_terminal)
buttonSend = Button(panelFrame, text="Send", command=send_entry_to_terminal)
buttonSend.pack(side=LEFT)
panelFrame.pack(fill=X, expand=1)
# Получение tty с которым будет работать терминал
os.system('xterm -into %d -geometry 160x50 -sb -e "tty > /tmp/pyguitty.txt"' % wid)
fp=open('/tmp/pyguitty.txt', 'r')
ttyDevice=fp.readline().strip();
fp.close();
print("tty info: "+ttyDevice)
# Открытие терминала с шеллом. Перед запуском шелла выводится рабочий tty
os.system('xterm -into %d -geometry 160x50 -sb -e "tty; sh" &' % wid)
root.mainloop()
input.sh
#!/bin/bash
echo "Укажите третий октет IPv4 адреса:"
read -p "> " subNet
echo "Вы ввели $subNet"
echo "Задержка 3 секунды..."
sleep 3
echo "Скрипт завершен"