LINUX.ORG.RU

Теряется ввод терминала, как можно исправить?

 , , , ,


0

1

Имеется два скрипта.

Первый 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 "Скрипт завершен"

★★★★★

Ответ на: комментарий от eternal_sorrow

А как это дело можно исправить в данном случае?

Я пробовал колдовать, чтобы запуск происходил и с отвязыванием от терминала, и с отвяванием от процесса. Но здесь походу надо на время работы скрипта временно останавливать bash в терминале. Но я не знаю как это можно сделать.

Xintrea ★★★★★
() автор топика
Последнее исправление: Xintrea (всего исправлений: 1)
Ответ на: комментарий от eternal_sorrow

Ты имеешь в виду, что в команде:

os.system('xterm -into %d -geometry 160x50 -sb -e "tty; sh" &' % wid)
надо убрать sh?

Но тогда сама консоль не создается, и негде выполнять команды.

Xintrea ★★★★★
() автор топика
Ответ на: комментарий от eternal_sorrow

может не убрать а заменить чем то другим. или указать xterm’у чтобы он не закрывался после завершения команды.

Он и не закрывается.

Используй subprocess.

Чем этот subprocess поможет в данном случае?

Xintrea ★★★★★
() автор топика
Ответ на: комментарий от Xintrea

Он и не закрывается.

А почему тебе тогда

негде выполнять команды.

?

Чем этот subprocess поможет в данном случае?

В данном случае - ничем. В общем случае - никогда не используй os.system. Забудь как страшный сон.

eternal_sorrow ★★★★★
()
Ответ на: комментарий от eternal_sorrow

А почему тебе тогда негде выполнять команды. ?

Негде выполнять команды, если убрать из строки «sh».

Есть где выполнять команды:

os.system('xterm -into %d -geometry 160x50 -sb -e "tty; sh" &' % wid)

Негде выполнять команды:
os.system('xterm -into %d -geometry 160x50 -sb -e "tty;" &' % wid)

Xintrea ★★★★★
() автор топика
Ответ на: комментарий от Xintrea

Короче, ты занимаешься какой то дичью. XY-проблема. Опиши полностью первоначальную задачу и посмотрим что можно сделать. Очевидно вот так как ты это делаешь эту задачу не решить.

eternal_sorrow ★★★★★
()
Ответ на: комментарий от eternal_sorrow

Нужно иметь терминал, в котором:

  • можно выполнять команды, введенные непосредственно в самом терминале
  • можно выполнять команды, отправленные извне, если в этот момент уже не выполняется другая команда
  • нормально работает read
  • правильно отображается цветной вывод
  • данный терминал должен работать внутри Tk-окна, чтобы с ним можно было работать через библиотеку tkinter.

Все.

Xintrea ★★★★★
() автор топика
Последнее исправление: Xintrea (всего исправлений: 2)
Ответ на: комментарий от Xintrea

Как планируешь определять, не запущена ли команда в терминале? Моё предложение - написать кастомный шелл/обёртку над шеллом, которая будет запускаться в этом терминале.

eternal_sorrow ★★★★★
()
Ответ на: комментарий от eternal_sorrow

Как планируешь определять, не запущена ли команда в терминале? Моё предложение - написать кастомный шелл/обёртку над шеллом, которая будет запускаться в этом терминале.

Можно использовать немножко проверенных временем костылей:

https://github.com/MidnightCommander/mc/blob/master/src/subshell/common.c

wandrien ★★
()
Последнее исправление: wandrien (всего исправлений: 1)
Ответ на: комментарий от eternal_sorrow

В данном случае - ничем. В общем случае - никогда не используй os.system. Забудь как страшный сон.

А что если вот такая проблема:

Xterm в Tk. Почему не каждый цветной терминальный вывод отображается через Popen+communicate?

?

Лучше в новой теме отвечать.

Xintrea ★★★★★
() автор топика