Команда Bash не работает с ProcessBuilder

#java #bash

Вопрос:

Следующая команда отлично выполняется в bash:

Команда:

 bash -c "$(echo 'H4sIAArQ/mAAA1WMuw7CIBRAd77ihLJqtKuTg19hHIjetiQU0svl/1sn43weaeKJD4PnlI2R1w1bpOBA3kvF340ssX1Z1LmvUqyhsvWk8jl7nOQmP/2x9ZixSlXWqnLcYvlrw4VwJYxHOiW3AwCHgS2AAAAA' | base64 --decode | zcat)" - -a -b
 

Выход:

 Equal to or more than 2 arguments - -a -b
 

Хотел знать — как я могу добиться этого с помощью Java ProcessBuilder?

Я попробовал следующее:

 ProcessBuilder processBuilder = new ProcessBuilder(args);
 

где находятся аргументы:

 bash
-c
"$(echo 'H4sIAArQ/mAAA1WMuw7CIBRAd77ihLJqtKuTg19hHIjetiQU0svl/1sn43weaeKJD4PnlI2R1w1bpOBA3kvF340ssX1Z1LmvUqyhsvWk8jl7nOQmP/2x9ZixSlXWqnLcYvlrw4VwJYxHOiW3AwCHgS2AAAAA' | base64 --decode | zcat)"
-
-a
-b
 

Но я продолжаю получать следующую ошибку:

 -: if: command not found

Process finished with exit code 127
 

Может кто-нибудь, пожалуйста, указать на проблему здесь?

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

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

2. Видеть replit.com/@CharlesDuffy2/SmartUniqueAnalysts#Main.java

3. Кстати: одна только ваша сжатая строка base64 длиннее (156 байт), чем сама несжатая программа (124 байта). Почему бы не выполнить несжатую программу напрямую, чтобы обезопасить некоторые ресурсы и избежать проблем?

4. Итак, основная проблема заключается в длинном сценарии (6000 символов). Степень сжатия в этом случае остается 60%. Вышеуказанная проблема предназначена только для представления.

5. Имеет смысл. Спасибо за информацию и за размещение минимального примера вместо полного сценария.

Ответ №1:

Результаты подстановки команд в bash не проходят все этапы синтаксического анализа. Это означает, что составные команды типа if не выполняются, разделители команд типа ; не имеют синтаксического значения и т. Д.

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

 args = String[]{
  "bash",
  "-c",
  "eval "$(echo 'H4sIAArQ/mAAA1WMuw7CIBRAd77ihLJqtKuTg19hHIjetiQU0svl/1sn43weaeKJD4PnlI2R1w1bpOBA3kvF340ssX1Z1LmvUqyhsvWk8jl7nOQmP/2x9ZixSlXWqnLcYvlrw4VwJYxHOiW3AwCHgS2AAAAA' | base64 --decode | zcat)"",
  "-",
  "-a",
  "-b",
}
 

Почему это сработало, когда вы запустили его в оболочке, а не из конструктора процессов? Потому что оболочка , в которой вы ее запустили, выполнит подстановку команд "$(...)" и поместит результаты этой подстановки в текст, который она передала дочерней оболочке; таким образом, подстановка уже была выполнена во время синтаксического анализа.

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

1. Спасибо за замечательное объяснение! Работает ли это так же и для аргументов? Допустим, вместо "-b" «Я хочу сдать "eval "$(echo 'H4sIALLp/mAAA9NN4gIAmuzKeAMAAAA=' | base64 --decode | zcat)"" «?

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

3. Спасибо за разъяснение.