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