Bash: интерактивная удаленная подсказка

Это охвачено в главе 10 Драйверов устройств Linux, 3-го выпуска, Corbet и др. Это доступно бесплатно онлайн, или можно бросить некоторого O'Reilly шекелей путь к мертвому дереву или формам электронной книги. Часть, относящаяся к Вашему вопросу, начинается на странице 278 в первой ссылке.

Если это имеет значение вот моя попытка перефразировать те три страницы плюс другие биты, которые я Погуглил:

  • При регистрации общего обработчика IRQ ядро проверяет что также:

    a. никакой другой обработчик не существует для того прерывания, или

    b. все ранее зарегистрированные также требуемое совместное использование прерывания

    Если любой случай применяется, он затем проверяет что Ваш dev_id параметр уникален, так, чтобы ядро могло дифференцировать несколько обработчиков, например, во время демонтажа обработчика.

  • Когда PCI ¹ устройство повышает линию IRQ, обработчика прерываний ядра низкого уровня называют, и это в свою очередь называет всех зарегистрированных обработчиков прерываний, пасуя назад каждого dev_id Вы раньше регистрировали обработчик через request_irq().

    dev_id оцените должно быть уникальным для машины. Распространенный способ сделать, который должен передать указатель на для каждого устройства struct Ваше использование драйвера для управления тем устройством. Так как этот указатель должен быть в пространстве памяти Вашего драйвера для него, чтобы быть полезным для драйвера, это в силу самого факта уникально для того драйвера. ²

    Если будет несколько драйверов, зарегистрированных для данного прерывания, то их все назовут, когда любое из повышений устройств, которые совместно использовали линию прерывания. Если это не было устройство Вашего драйвера, которое сделало это, обработчик прерываний Вашего драйвера будет передан a dev_id значение, которое не принадлежит ему. Обработчик прерываний Вашего драйвера должен сразу возвратиться, когда это происходит.

    Другой случай - то, что Ваш драйвер управляет несколькими устройствами. Обработчик прерываний драйвера получит один из dev_id значения известны драйверу. Ваш код, как предполагается, опрашивает каждое устройство для обнаружения, какой повысил прерывание.

    Примером, который и др. дают Corbet, является пример параллельного порта ПК. Когда это утверждает линию прерывания, это также устанавливает главный бит в своем первом регистре устройства. (Таким образом, inb(0x378) & 0x80 == true, принятие стандартной нумерации порта I/O.), Когда Ваш обработчик обнаруживает это, он, как предполагается, делает свою работу, затем очищает IRQ путем записи значения, считанного из порта I/O назад к порту с главным очищенным битом.

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

  • Когда Ваш обработчик прерываний говорит ядру, что это обработало прерывание, которое не мешает ядру продолжить называть любые другие обработчики зарегистрированными для того же самого прерывания. Это неизбежно, если необходимо совместно использовать линию прерывания при использовании инициированных уровнем прерываний.

    Предположите, что два устройства утверждают ту же линию прерывания одновременно. (Или по крайней мере, так закройтесь вовремя, что ядро не имеет времени для вызова обработчика прерываний, чтобы очистить строку и таким образом рассматривать второе утверждение как отдельное.) Ядро должно назвать все обработчики для той линии прерывания, чтобы дать каждому шанс запросить его связанные аппаратные средства, чтобы видеть, необходимо уделять внимание ли этому. Для двух различных драйверов довольно возможно успешно обработать прерывание в том же, проходят через список обработчика для данного прерывания.

    Из-за этого обязательно, чтобы Ваш драйвер сказал устройству, что этому удается очистить его утверждение прерывания когда-то перед возвратами обработчика прерываний. Мне не ясно, что происходит иначе. Непрерывно утверждаемая линия прерывания будет или приводить к ядру, непрерывно называя общих обработчиков прерываний, или это замаскирует способность ядра видеть новые прерывания, таким образом, обработчики никогда не будут называть. Так или иначе, авария.


Сноски:

  1. Я указал PCI выше, потому что все вышеупомянутое принимает инициированные уровнем прерывания, как используется в исходной спецификации PCI. ISA использовал инициированные фронтом сигнала прерывания, которые сделали совместное использование хитрого в лучшем случае и возможного даже затем только при поддержке аппаратными средствами. PCIe использует сообщенные сообщению прерывания; сообщение прерывания содержит уникальное значение, которое ядро может использовать для предотвращения циклической игры предположения, требуемой с совместным использованием прерывания PCI. PCIe может избавить от самой необходимости совместное использование прерывания. (Я не знаю, делает ли это на самом деле, просто что это имеет потенциал к.)

  2. Драйверы ядра Linux вся доля то же пространство памяти, но несвязанный драйвер, как предполагается, не слоняется без дела в чьем-либо пространстве памяти. Если Вы не раздаете тот указатель, можно быть вполне уверены, другой драйвер не собирается придумывать то же самое значение случайно самостоятельно.

16
10.11.2013, 22:01
4 ответа

Попробуйте что-то вроде этого:

$ ssh -t yourserver "$(<your_script)"

-t вызывает tty выделение, $(<your_script) читает целый файл, и в этом случается, передает содержание как один аргумент ssh, который будет выполняться оболочкой удаленного пользователя.

Если для сценария нужны параметры, передайте их после сценария:

$ ssh -t yourserver "$(<your_script)" arg1 arg2 ...

Работы для меня, не уверенный, если это универсально все же.

22
27.01.2020, 19:48
  • 1
    Это точно, что я искал, спасибо! –  Anthony Ananich 10.11.2013, 19:25
  • 2
    Хорошее решение, но там способ передать аргумент your script, при сохранении преимуществ синтаксиса Вы использовали в своем ответе? Используя ssh -t yourserver "$(<your_script --some_arg)" просто результаты в bash: --some_arg: command not found. –  sampablokuper 02.01.2018, 20:50
  • 3
    @sampablokuper: попробовать ssh ... $(<script) script_arg1 script_arg2 ... –  Mat 02.01.2018, 22:13
  • 4
    @Mat, спасибо, WFM :) Возможно, добавьте его к телу Вашего ответа? –  sampablokuper 03.01.2018, 18:55

Ваша проблема - это ssh запускает вход в систему, неинтерактивную оболочку на удаленной машине. Очевидное легкое решение состояло бы в том, чтобы скопировать сценарий в удаленный сервер и выполнить его оттуда:

scp myscript.sh root@server:/tmp && ssh root@server /tmp/myscript.sh

Если бы копирование не является опцией по любой причине, я изменил бы сценарий, чтобы сначала соединить и проверить если $1 установлен, затем повторно подключите и установите по мере необходимости:

OUT=$(ssh root@server rpm -qa | grep "$1");
if [ "$OUT" != "" ] ; then
    echo "$1 already installed"
else
   read -p "Package $1 is not installed. Do you want to install it (y/n)?" choice
   if [ "$choice" -eq "y" ]; then
       ssh root@server yum install "$1"
   fi
fi
3
27.01.2020, 19:48
  • 1
    Это - то, чего я боялся. Соединение с ssh является самой долгой операцией, и я старался избегать его. –  Anthony Ananich 10.11.2013, 17:49
  • 2
    @AnthonyAnanich можно сэкономить время установления соединения путем установки основного соединения. –  Gilles 'SO- stop being evil' 10.11.2013, 22:02
  • 3
    @Gilles я думал о предложении что, но я думал, что он не будет работать с моим предложением. Если 1-е соединения SSH будут действовать как ведущее устройство, то это будет закрыто после $OUT=$(ssh root@server rpm -qa | grep "$1"); выходы и затем 2-е соединение займут столько же времени сколько первое.Я неправ? –  terdon♦ 10.11.2013, 22:18
  • 4
    @terdon что-то как ssh -M foo.example.com sleep 99999999 или ssh -M foo.example.com read <somefifo как ведущее устройство и уничтожают его явно (с kill или echo done >somefifo) когда Вы сделаны. –  Gilles 'SO- stop being evil' 10.11.2013, 22:30

Вот хорошее объяснение.

Таким образом, я адаптировал сценарий к

hostname
echo -n "Make your choice :"
read choice
echo "You typed " ${choice}
echo done

и это не работало.

таким образом, я переместил сценарий в удаленное для предотвращения локального перенаправления на ssh. (Мои команды находятся в файле, названном f),

cat f | ssh user@remotehost.com 'cat >remf'
ssh user@remotehost bash remf

Это работало. Вот вывод:

christian@clafujiu:~/tmp$ ssh localhost bash tmp/f
christian@localhost's password: 
Linux clafujiu 2.6.32-52-generic #114-Ubuntu SMP Wed Sep 11 19:00:15 UTC 2013 i686 GNU/Linux
Sun Nov 10 14:58:56 GMT 2013
Make your choice :abc
You typed  abc
done

Поскольку @terdon упомянул, что исходное содержание должно было запустить локальные скрипты удаленно, удаленная копия может быть автоматизирована, это - всего один пример все на одной строке.

REMID=`cat f |ssh user@remotehost 'cat > remf_$$; echo $$'` ;ssh root@redtoadservices.com "bash remf_${REMID} ; rm -v remf_${REMID}"
0
27.01.2020, 19:48
  • 1
    Как это "работало"? Вы запускали этот скрипт с bash -s < script.sh как OP сделал? Вы могли включать объяснение в свой ответ вместо того, чтобы связаться с ним? –  terdon♦ 10.11.2013, 16:33
  • 2
    Ой, очень жаль я забыл добавлять что-то критическое. Я также скопировал сценарий в удаленное для предотвращения локального перенаправления. Я добавлю это к своему ответу для прояснения. –  X Tian 10.11.2013, 16:53
  • 3
    При копировании сценария в удаленное, проблема уходит. Проблема OP - то, что он пытается дать интерактивный вход локальному сценарию, работающему удаленно. Конечно, это будет работать Вас, копируют его. OP хотят запустить этот скрипт при соединении с удаленным сервером, по-видимому, со многими удаленными серверами. Я сомневаюсь относительно копирования, это практично, если Вы не автоматизируете его. спасибо –  terdon♦ 10.11.2013, 16:57

В прошлом я несколько раз искал решение этой проблемы, но так и не нашел полностью удовлетворительного решения. При подключении к ssh ваша интерактивность теряется. Два соединения (scp/ssh )медленнее, и ваш временный файл может остаться без дела. И весь скрипт в командной строке часто заканчивается адом.

Недавно я обнаружил, что размер буфера командной строки обычно довольно велик ('getconf ARG _MAX > 2MB, где я смотрел ). И это заставило меня задуматься о том, как я мог бы использовать это и смягчить проблему побега.

Результат:

ssh -t <host> /bin/bash "<(echo "$(cat my_script | base64 | tr -d '\n')" | base64 --decode)" <arg1>...

или используя здесь документ и кошку:

ssh -t <host> /bin/bash $'<(cat<<_ | base64 --decode\n'$(cat my_script | base64)$'\n_\n)' <arg1>...

Я расширил эту идею, чтобы создать полностью работающий пример сценария BASH sshx, который может запускать произвольные сценарии (, а не только BASH ), где аргументы могут быть также локальными входными файлами через ssh. См. здесь .

0
27.01.2020, 19:48

Теги

Похожие вопросы