Вопрос или проблема
У меня есть файл в $HOME/bin (прежде чем вы спросите, да, он в моем пути) с именем test
, который я подтвердил, что может быть выполнен без проблем, когда я запускаю его с полным путем к файлу. Однако у меня возникает очень странная проблема, когда я не запускаю его таким образом. Когда я просто ввожу test
в терминале, он ничего не делает и сразу возвращается. Я знаю, что это не проблема нахождения файла по нескольким причинам:
-
Нет сообщения об ошибке. Обычно, если файл не может быть найден или выполнен, появляется сообщение об этом.
-
Команда
which test
все равно возвращает правильный путь к файлу. -
Наверное, самое странное – скрипт нормально работает, когда запускается через
strace
. Я попытался использоватьstrace
, чтобы выяснить, что происходит, но когда я запустил его сstrace
, он работал как ожидалось без проблем.
test
— это неудачное имя, его использование приводит к путанице, это стандартная утилита для условных тестов. (На самом деле, это та же команда, что и [
в if [ ... ]
, которая выглядит как синтаксическая конструкция, но на самом деле является обычной командой.)
test
также встроена в, например, Bash, так что просто введя test
, она никогда не ищет ваш бинарный файл в пути.
bash$ help test | head
test: test [expr]
Оценить условное выражение.
Завершает работу со статусом 0 (истина) или 1 (ложь) в зависимости от
оценки EXPR. Выражения могут быть унарными или бинарными.
[...]
test
без аргументов просто возвращает 1 (ложь).
Запуск strace test
не задействует встроенную команду оболочки, так как strace
не реализует никаких утилит самостоятельно. Он просто использует то, что находит в вашем PATH
. Обратите внимание, что, вероятно, у вас есть стандартный test
в /bin/test
или /usr/bin/test
, так что если он окажется первым в PATH
, strace
запустит его.
В моем Bash команда which
также является внешней командой, так что она не знает о встроенных командах. С другой стороны, команда type
встроена в оболочку, и type test
покажет, что test is a shell builtin
.
Смотрите также: Почему не использовать “which”? Что использовать тогда?
Ответ или решение
Проблема, с которой вы столкнулись, связана с тем, что имя вашего исполняемого файла test
совпадает с именем стандартной утилиты test
, которая является встроенной командой в оболочке Bash и, вероятно, в других оболочках. Вот подробный разбор ситуации и возможные пути её решения:
Описание проблемы
-
Вызов встроенной команды: Когда вы просто вводите
test
в терминале, оболочка Bash не ищет исполняемый файл в вашем пути ($PATH
), а вызывает встроенную командуtest
. Эта встроенная команда проверяет условные выражения и, если не переданы аргументы, возвращает код завершения 1 (что обозначает "ложь") и завершает выполнение. -
Работа с
strace
: Когда вы используетеstrace test
, происходит вызов вашей программы, посколькуstrace
игнорирует встроенные команды и взаимодействует только с исполняемыми файлами. Именно поэтому ваш скрипт работает корректно при вызове черезstrace
. -
Доступность команды: Использование команды
which test
также показывает путь к вашей программе, но это не учитывает встроенные команды, поэтому она не может указать на то, чтоtest
является встроенной командой в оболочке.
Решение проблемы
Чтобы избежать конфликта между вашим скриптом и встроенной командой test
, вы можете сделать следующее:
-
Измените имя вашего файла: Это самый простой и рекомендуемый метод. Переименуйте ваш скрипт в что-то более уникальное, например,
mytest
илиrun_test
. Это гарантирует, что вы всегда будете вызывать именно вашу программу, а не встроенную команду. -
Запуск из абсолютного пути: Если вы хотите продолжать использовать имя
test
, вы можете запускать ваш скрипт с полным путём, например:$HOME/bin/test
Однако это решение менее удобно, так как требует постоянного ввода полного пути.
-
Использование другой оболочки: В некоторых случаях вы можете использовать другую оболочку, которая не имеет встроенной команды
test
, например,sh
илиdash
, чтобы запустить ваш скрипт, но это не всегда может быть целесообразно.
Проверка идентификации
Чтобы проверить, является ли команда встроенной, вы можете использовать команду type
:
type test
В результате выполнения этой команды вы увидите, что test
является встроенной командой, тогда как путь к вашему исполняемому файлу не будет отображаться.
Заключение
Проблема, с которой вы столкнулись, была вызвана конфликтом имён с встроенной командой в оболочке Bash. Рекомендуемое решение — переименовать ваш исполняемый файл, что соответствует лучшим практикам программирования и помогает избежать подобных ситуаций в будущем.