Оболочка: удаление «eval» в пользу чего-то, что может содержать внешние переменные, само является переменной и содержит подоболочку - PullRequest
0 голосов
/ 26 апреля 2019

Я прочитал это: Скобки для subshell не работают, когда хранятся в переменной и это: http://mywiki.wooledge.org/BashFAQ/048 и они были проницательны и поучительны, и я любил их читать.

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

Таким образом, я вынужден согласиться с тем, что eval является злом и имеет технические недостатки помимо недостатков безопасности.

Как вы решаете следующее:

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

  2. Тело такое же, но использует переменные, заполненные в первом потоке. И НЕ является единственной командой

  3. Тело само по себе работает подоболочками

  4. Заменяющее решение должно быть не последовательным, а "синхронным", как eval. (он не заставляет завершающие команды ждать своего возврата для выполнения)

Вот что мы получаем:

Наш переключатель if и elif, запускающий наши скрипты для второго терминала или "второго потока":

if [[ "$operating_system" = "Ubuntu" || "$operating_system" = "Debian GNU/Linux" ]]
then
    eval "$gnome_opening_faf_script $faf_script $gnome_closing_faf_script"
elif [ "$operating_system" = "Kubuntu" ]
then
    eval "$konsole_opening_faf_script $faf_script $konsole_closing_faf_script"
elif [ "$operating_system" = "elementary OS" ]
then
    eval "$io_opening_faf_script $middlescript $io_closing_faf_script"
else
    eval "$xterm_opening_faf_script $faf_script $xterm_closing_faf_script"
fi

Переменная основного тела второй нити:

faf_script='echo "expecting you to type in Forged Alliances Launch options";
echo "reminder : look in your home folder, theres a file there with the contents to be pasted";
echo "once thats done edit steam settings in order to enable Proton for all games";
steam -login '$steam_user_name' '$steam_password' -applaunch 9420 &
echo "waiting for Forged Alliance to be installed, Game.prefs to exits and Forged Alliance to be shut down";
echo "you may also type \"continue\" to exit this while loop"
echo -n "if you feel the conditions for continuing sucessfully have been met... ";
( i=1;
sp="/-\|";
no_config=true;
while $no_config;
do printf "\b${sp:i++%${#sp}:1}";
[[ ! $(pidof SupremeCommande) && -f $origin/steamapps/compatdata/9420/pfx/drive_c/users/steamuser/Local\ Settings/Application\ Data/Gas\ Powered\ Games/Supreme\ Commander\ Forged\ Alliance/Game.prefs ]] && no_config=false;
sleep 1;
done;
kill $$;
) &;
child_pid=$!;
while $no_config;
do read -r typed_continue;
[[ "$typed_continue" = "continue" ]] && no_config=false;
sleep 1;
done;
kill $child_pid;
echo "";
'

И открытие закрывающих переменных, которые позволяют запускать второй поток скрипта различными терминалами в зависимости от распределения.

gnome_opening_faf_script='gnome-terminal --tab --active --title="install & run steam, steamcmd, FA" -- bash -c '"'"''
konsole_opening_faf_script='konsole -e /bin/bash --rcfile <(echo '"'"''
io_opening_faf_script='io.elementary.terminal -e "bash -c '"'"'curl  wttr.in/bydgoszcz'"'"';'"'"'sleep 3'"'"''
xterm_opening_faf_script='xterm -T "install & run steam, steamcmd, FA" -e '"'"''

gnome_closing_faf_script='gnome-terminal -- bash -c "cd faf; ./downlords-faf-client";'"'"''
konsole_closing_faf_script='konsole -e /bin/bash --rcfile <(echo "cd faf; ./downlords-faf-client; exit 0") &'"'"') &'
io_closing_faf_script='io.elementary.terminal -e "cd faf; ./downlords-faf-client";'"'"''
xterm_closing_faf_script='xterm -T "FAF" -e "cd faf; ./downlords-faf-client";'"'"' &'

Обычно, когда люди предлагают замены для оценки, контексты не упрощаются. eval работает один echo "hello world".

здесь это не мой случай, и я не смог применить ни одно из решений.

Ответы [ 2 ]

2 голосов
/ 26 апреля 2019

Давайте начнем с общего обзора того, что вы хотите сделать: запустите некоторое количество произвольных сценариев (содержащихся в строках) на отдельной вкладке эмулятора терминала для конкретной ОС. Содержимое скриптов не имеет большого значения, поэтому давайте просто скажем, что мы имеем их в двух переменных:

faf_script='...'
download_script='...'

Теперь нам нужна функция, которая выглядит примерно так:

run_scripts () {
    for script in "$@"; do
        run_in_tab "$script"
    done
}

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

Далее мы на самом деле определяем run_in_tab в зависимости от ОС.

case $operating_system in
  Ubuntu|"Debian GNU/Linux")
    run_in_tab () {
      gnome-terminal .....
    } ;;

  Kubuntu)
    run_in_tab () {
        konsole ......
    } ;;

  "elementary OS")
    download_script='...'   # For whatever reason, this is different; override it
    run_in_tab () {
        konsole ......
    } ;;

  *) run_in_tab () {
       xterm ....
     } ;;
esac

Как только это будет сделано, мы просто позвоним run_scripts:

run_scripts "$faf_script" "download_script"
0 голосов
/ 26 апреля 2019

Альтернатива, которая в основном делает то же самое, что и eval, но проще (по крайней мере для меня) в сложных случаях, подобных этому:

goDo() {
  local tmp=$(mktemp) # create a guaranteed unique temporary filename
  echo "$1" >| $tmp   # send the passed-in string to that file
  . $tmp              # *source* the file back into the local context
}

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

Если что-то сломается, у вас есть весь файл, доступный для отладки. Я рекомендую установить set -x отладку для первых нескольких тестовых прогонов, просто чтобы убедиться, что вы видите, что ожидаете.

...