Ожидание, похоже, не работает вне tty в определенном контексте

#linux #shell #expect

Вопрос:

Я пытался использовать expect, и, похоже, он не работает вне tty в определенном контексте

Это связано с попыткой вызвать команду без взаимодействия для создания пакета makepkg

 $ makepkg -Ccfi --noconfirm
==> Installing package test-delta with pacman -U...

We trust you have received the usual lecture from the local System
Administrator. It usually boils down to these three things:

    #1) Respect the privacy of others.
    #2) Think before you type.
    #3) With great power comes great responsibility.

sudo: a terminal is required to read the password; either use the -S option to re
ad from standard input or configure an askpass helper
sudo: a password is required
==> WARNING: Failed to install built package(s).
 

Хотя я смог правильно вызвать его с помощью следующего:

 $ sudo -S -v <<< 

У меня все еще были подобные проблемы с подсказками пароля при выполнении программ, не связанных с Bash. И то, что я думал, было бы легко исправить, оказалось не всегда работающим... Мне нужно, чтобы это обобщенное решение работало должным образом

Ниже приведен сценарий ожидания...

 cat > run.sh <<"EOF"
expect -c 'spawn makepkg -Ccfi --noconfirm; expect "*password*"; send "passwordn"; interact'
EOF
 

И он успешно запускается на терминале, устанавливая пакет

 $ ./run.sh
...
==> Installing package test-delta with pacman -U...
[sudo] password for op:
loading packages...
warning: test-delta-1.0.0-1 is up to date -- reinstalling
resolving dependencies...
looking for conflicting packages...

Packages (1) test-delta-1.0.0-1

Total Installed Size:  0.00 MiB
Net Upgrade Size:      0.00 MiB

:: Proceed with installation? [Y/n]
(1/1) checking keys in keyring                            [##############################] 100%
...
 

Запуск сценария на tty, похоже, сработал. Однако на самом деле этот сценарий выполнялся toast чем-то вроде бегуна задач, смешанного с Докером , и там он потерпел бы неудачу. (Я действительно пытался смоделировать поведение Тоста в bash и никак не мог заставить его потерпеть неудачу) Вывод выглядит так, когда я пытаюсь запустить его через тост:

 ➤ toast --shell
[INFO] Ready to run 2 tasks: init and main.
[INFO] Running task init…
[INFO] Running task main…
spawn makepkg -Ccfi --noconfirm
==> Making package: test-delta 1.0.0-1 (Sat 29 May 2021 01:58:26 AM UTC)
...
==> Finished making: test-delta 1.0.0-1 (Sat 29 May 2021 01:58:27 AM UTC)
==> Installing package test-delta with pacman -U...

We trust you have received the usual lecture from the local System
Administrator. It usually boils down to these three things:

    #1) Respect the privacy of others.
    #2) Think before you type.
    #3) With great power comes great responsibility.

[sudo] password for op:
[INFO] Preparing a shell…
[op@9205d39656e4 scratch]$ pacman -Qi test-delta
error: package 'test-delta' was not found
 

I tried to simulate it's failing behavior manually for those that don't have the program installed. So I try to run without an attachment to current tty

 # https://superuser.com/a/1430883
(setsid ./run.sh) </dev/null |amp; cat
 

The above does not fail, so I also tried the following to make it fail

 (setsid ./run.sh) <>/dev/null
 

Both unexpectedly worked, so I looked at toast and it seemed to execute commands like this.

So I try to use sh as well...

 sh -c '(setsid ./run.sh) </dev/null |amp; cat'
 

AH (╯°□°)╯︵ ┻━┻. This command succeeds while Toast fails? How does the command ran within Toast fails? I'm not sure what to do at this point. Some other tricks like unbuffer -p didn't seem to change things either...

I don't think it's due to any process namespaces created by Docker? I don't know what to guess at this point, I don't think Toast is doing anything special? I recon others have had similar problems that may be familiar with this issue - but if you wish to reproduce this on your own, I have the following setup in a directory:

You can replicate this with this toast.yml file

 image: archlinux
default: main
tasks:
  init:
    command: |
      set -Eeuo pipefail
      pacman -Syu --noconfirm base-devel sudo man-db expect

      sed -ie 's/# %sudo/%sudo/g' /etc/sudoers
      groupadd sudo

      useradd -m op -s /bin/bash -G sudo
      chpasswd <<< 'op:password'

  main:
    dependencies: [ init ]
    cache: false
    user: op
    mount_paths:
      - .
    command: |
      ./run.sh
 

This PKGBUILD file

 # Maintainer: Edwin Kofler <edwin@kofler.dev>
pkgname='test-delta'
pkgver='1.0.0'
pkgrel='1'
pkgdesc='Desc'
arch=('any')
license=('unknown')
depends=(bash)

# prepare() {
#   :
# }

# build() {
#   :
# }

# check() {
#   :
# }

package() {
    mkdir "$pkgname-$pkgver"
    cd "$pkgname-$pkgver"

    mkdir -p "$pkgdir/usr/bin"
    cat > "$pkgdir/usr/bin/test-delta" <<< "echo 'WORKING WORKING WORKING WORKING' -------------------"
    chmod  x "$pkgdir/usr/bin/test-delta"
}
 

и этот run.sh файл

 expect -c 'spawn makepkg -Ccfi --noconfirm; expect "*password*"; send "passwordn"; interact'
 

Запустив toast --shell в том же каталоге...

 $ toast --shell
...
[INFO] Preparing a shell…
[op@69bee81d643f scratch]$ pacman -Qi test-delta
error: package 'test-delta' was not found
 


Комментарии:

1. sudo без -S использования (и требует) /dev/tty . Это отдельно от stdin,out,err,поэтому все ваши различные и творческие способы перенаправления stdin, out не влияют на это. И не делает setsid , что (только) влияет на доставку сигналов от драйвера tty, которые здесь не имеют отношения к делу. Я почти уверен, что docker влияет на /dev/tty и является вашей проблемой здесь , но я сам не использую docker и не знаю правильного решения.

2. Есть какая-то особая причина, по которой вы просто не работаете makepkg как root ?


passwordn'
$ source makepkg -Ccfi --noconfirm
У меня все еще были подобные проблемы с подсказками пароля при выполнении программ, не связанных с Bash. И то, что я думал, было бы легко исправить, оказалось не всегда работающим… Мне нужно, чтобы это обобщенное решение работало должным образом

Ниже приведен сценарий ожидания…


И он успешно запускается на терминале, устанавливая пакет


Запуск сценария на tty, похоже, сработал. Однако на самом деле этот сценарий выполнялся toast чем-то вроде бегуна задач, смешанного с Докером , и там он потерпел бы неудачу. (Я действительно пытался смоделировать поведение Тоста в bash и никак не мог заставить его потерпеть неудачу) Вывод выглядит так, когда я пытаюсь запустить его через тост:


I tried to simulate it’s failing behavior manually for those that don’t have the program installed. So I try to run without an attachment to current tty


The above does not fail, so I also tried the following to make it fail


Both unexpectedly worked, so I looked at toast and it seemed to execute commands like this.

So I try to use sh as well…


AH (╯°□°)╯︵ ┻━┻. This command succeeds while Toast fails? How does the command ran within Toast fails? I’m not sure what to do at this point. Some other tricks like unbuffer -p didn’t seem to change things either…

I don’t think it’s due to any process namespaces created by Docker? I don’t know what to guess at this point, I don’t think Toast is doing anything special? I recon others have had similar problems that may be familiar with this issue — but if you wish to reproduce this on your own, I have the following setup in a directory:

You can replicate this with this toast.yml file


This PKGBUILD file


и этот run.sh файл


Запустив toast --shell в том же каталоге…


Комментарии:

1. sudo без -S использования (и требует) /dev/tty . Это отдельно от stdin,out,err,поэтому все ваши различные и творческие способы перенаправления stdin, out не влияют на это. И не делает setsid , что (только) влияет на доставку сигналов от драйвера tty, которые здесь не имеют отношения к делу. Я почти уверен, что docker влияет на /dev/tty и является вашей проблемой здесь , но я сам не использую docker и не знаю правильного решения.

2. Есть какая-то особая причина, по которой вы просто не работаете makepkg как root ?