Нахождение пути текущего исполняемого файла без/proc/self/exe

Ответ

POSIX-совместимый:

command -v <the_command>

Для bash конкретных сред:

hash <the_command> # For regular commands. Or...
type <the_command> # To check built-ins and keywords

Объяснение

Избегать which. Это не только внешний процесс, который вы запускаете из-за того, что выполняете очень мало (то есть встроенные функции, такие как hash, type или command, значительно дешевле), вы также можете полагаться на встроенные функции, которые действительно делают то, что вы хотите, в то время как Эффект внешних команд может легко варьироваться от системы к системе.

Зачем это нужно?

  • Многие операционные системы имеют which, который даже не устанавливает статус выхода , то есть if which foo даже не будет работать там и всегда сообщит, что foo существует, даже если его нет (обратите внимание, что некоторые оболочки POSIX, похоже, делают это и для hash).
  • Многие операционные системы заставляют which делать нестандартные и злые вещи, например, изменять вывод или даже подключаться к менеджеру пакетов.

Итак, не используйте which. Вместо этого используйте один из них:

$ command -v foo >/dev/null 2>&1 || { echo >&2 "I require foo but it's not installed.  Aborting."; exit 1; }
$ type foo >/dev/null 2>&1 || { echo >&2 "I require foo but it's not installed.  Aborting."; exit 1; }
$ hash foo 2>/dev/null || { echo >&2 "I require foo but it's not installed.  Aborting."; exit 1; }

(Незначительное замечание: некоторые предполагают, что 2>&- - это то же самое 2>/dev/null, но короче - , это не соответствует действительности . 2>&- закрывается FD 2, который вызывает ошибку в программе, когда она пытается записать в stderr, что сильно отличается от успешной записи в нее и отбрасывания вывода (и это опасно!))

Если ваш hash bang is /bin/sh, тогда вам следует позаботиться о том, что говорит POSIX. type и hash коды выхода не очень хорошо определены в POSIX, и hash, как видно, успешно завершается, когда команда не существует (еще не видели этого с type). Состояние выхода command хорошо определено POSIX, так что, возможно, один из них наиболее безопасный для использования.

Если ваш скрипт использует bash, правила POSIX больше не имеют значения, и оба type и hash становятся совершенно безопасными для использования. У type теперь есть -P для поиска только PATH, а у hash есть побочный эффект, заключающийся в том, что расположение команды будет хэшировано (для более быстрого поиска в следующий раз, когда вы ее используете), что обычно хорошо, так как вы, вероятно, проверяете его существование, чтобы реально использовать его.

В качестве простого примера, вот функция, которая запускает gdate, если она существует, в противном случае date:

gnudate() {
    if hash gdate 2>/dev/null; then
        gdate "$@"
    else
        date "$@"
    fi
}
183
задан Jonas 2 March 2011 в 13:32
поделиться

4 ответа

Некоторые интерфейсы для ОС:

Переносимый (но менее надежный) метод - использовать argv [0] . Хотя вызывающая программа может установить что угодно, по соглашению устанавливается либо путь к исполняемому файлу, либо имя, которое было найдено с помощью $ PATH .

Некоторые оболочки, включая bash и ksh, устанавливают переменную среды " ] _ " на полный путь к исполняемому файлу перед его выполнением. В этом случае вы можете использовать getenv ("_") , чтобы получить его. Однако это ненадежно, потому что не все оболочки это делают, и он может быть установлен на что угодно или остаться от родительского процесса, который не изменил его перед выполнением вашей программы.

342
ответ дан 23 November 2019 в 06:00
поделиться

AFAIK, не так. Также существует двусмысленность: что бы вы хотели получить в качестве ответа, если один и тот же исполняемый файл имеет несколько жестких ссылок, «указывающих» на него? (Жесткие ссылки на самом деле не «указывают», они являются одним и тем же файлом, просто в другом месте в иерархии FS.) После того, как execve () успешно выполняет новый двоичный файл, вся информация о его аргументах становится потеряно.

1
ответ дан 23 November 2019 в 06:00
поделиться

Если вам когда-либо приходилось поддерживать, скажем, Mac OS X, в которой нет / proc /, что ты бы сделал? Используйте #ifdefs для изолировать специфичный для платформы код (NSBundle, например)?

Да изоляция специфичного для платформы кода с помощью #ifdefs - это традиционный способ выполнения этого.

Другой подход - иметь чистый #ifdef без заголовка, который содержит объявления функций и помещает реализации в исходные файлы, специфичные для платформы. Например, посмотрите, как библиотека Poco C ++ делает нечто подобное для своего класса Environment .

3
ответ дан 23 November 2019 в 06:00
поделиться

Вы можете использовать argv [0] и проанализировать переменную среды PATH. Посмотрите: Пример программы, которая может найти себя

2
ответ дан 23 November 2019 в 06:00
поделиться