Я рассматриваю наиболее эффективный способ решения:
- Должен ли я преподнести предоставленную пользователем командную строку с исполняемым файлом оболочки
- Если да, каков будет этот исполняемый файл? (/bin/sh?/usr/bin/perl?/usr/bin/ksh? c:/../cmd.exe?)
Известно, что для запуска оболочки script из Java следует вместо этого запустить оболочку:
ProcessBuilder pb = new ProcessBuilder("/bin/sh", "script.sh", "arg1", "arg2);
Для запуска двоичного файла необходимо запустить сам файл:
ProcessBuilder pb = new ProcessBuilder("/path/binary", "arg1", "arg2);
Если двоичный файл выполняется с оболочкой, он вызывает ошибку:
ProcessBuilder pb = new ProcessBuilder("/bin/sh", "/path/binary", "arg1", "arg2);
(sh: cannot execute binary file)
Если оболочка script выполняется без двоичного кода оболочки, она вызывает ошибку:
ProcessBuilder pb = new ProcessBuilder("script.sh", "arg1", "arg2);
(error 2: file not found)
Я в ситуации, когда мое приложение не знает, что он запускает, двоичный или script.
Запущенное приложение является обработчиком событий, предоставляемым конечным пользователем. Скорее всего, это оболочка script, выполняемая под Unix; но это может быть *.cmd под Windows или Perl script, выполненный под некоторой неясной платформой. В конце концов, это Java.
Моя первая наивная попытка состояла в том, чтобы запустить командную строку с оболочкой и посмотреть, работает ли она. Если нет, попробуйте выполнить его как двоичный.
Это безобразно и рискованно: при некотором неизвестном сочетании платформы и оболочки второй запуск может по-прежнему выполнять script, второй раз, с непредсказуемыми результатами.
Кроме того, я не могу сказать, когда script запустился ОК и не удалось из-за какой-то собственной проблемы, когда я просто не могу его запустить.
Лучшее, что я сейчас рассматриваю:
- Прочитайте script и найдите любые непечатаемые байты
- Если найдено, считайте его двоичным
- Если нет, добавьте /bin/sh (или cmd.exe, если в Windows)
Пожалуйста, сообщите, если у вас есть какие-то идеи.
ОБНОВЛЕНИЕ/ЧАСТИЧНОЕ РЕШЕНИЕ
Спасибо всем, кто поделился своими мыслями со мной.
Оказывается, я смутил себя и остальную часть Интернета:)
Не требуется добавлять двоичный код перед введенной пользователем командной строкой, если:
- script находится в PATH
- (для Unix) script является исполняемым
- (для Unix) script имеет #!/path/to/interpreter
Пока я тестировал свой код, одно или другое из этих условий не выполнялось.: - (
После тщательного тестирования с нуля script был выполнен.
Точка 3 может выполняться только пользователем и должна быть документирована в Руководстве пользователя.
В связи с тем, как эти сценарии распространяются в целевую систему, они могут быть не исполняемыми и не могут быть в PATH.
Единственный путь, о котором я забочусь, является относительным, поэтому достаточно добавить a./к любому относительному пути.
Создание сценариев, исполняемых в Unix (и любой другой платформе), является более сложной задачей. Это не WORA. Размещение /bin/sh перед ним может помочь, но если я правильно помню Solaris, оболочка не выполнит неисполняемый script.
Я опубликую новое обновление позже на этой неделе.