Выполнение файла с использованием точечного пространства и косой черты

Я пытаюсь работать с существующей библиотекой кода, но столкнулся с проблемой. Короче говоря, я выполняю скрипт оболочки (позвольте назвать это A), первым действием которого является вызов другого скрипта (B). Script B находится в моем текущем каталоге (требование программы, которую я использую). В руководстве по программному обеспечению делается ссылка на bash, однако комментарии в A предполагают, что он был разработан в ksh. До сих пор я работал в bash.

Внутри A линия для выполнения B просто:

. B

Он использует синтаксис "dot space" для вызова программы. Это не делает ничего необычного, как sudo.

Когда я вызываю A без синтаксиса пространственного пространства, то есть:

./A

это всегда ошибки, говорящие, что он не может найти файл B Я добавил pwd, ls, whoami, echo $SHELL и echo $PATH в A для отладки и подтвердил, что B на самом деле там, скрипт работает с тем же $SHELL что и я в командной строке, скрипт это тот же пользователь, что и я, и сценарий имеет тот же путь поиска $PATH что и я. Я также проверял, выполняю ли я:

. B

в командной строке он работает отлично. Но если я изменил синтаксис внутри A до:

./B

вместо этого A успешно выполняется.

Аналогично, если я выполняю A с синтаксисом с пространственным пространством, тогда и то, и другое . B . B и ./B.

Подведение итогов:
./A работает только в том случае, если A содержит синтаксис ./B.
. A . A работает для A с ./B или . B . B синтаксис.

Я понимаю, что использование синтаксиса точечного пространства (т . A Е. . A) выполняется без наложения на подоболочку, но я не вижу, как это может привести к поведению, которое я наблюдаю, учитывая, что файл явно прямо там. Есть ли что-то, что мне не хватает в отношении нюансов синтаксиса или рабочих областей родительского/дочернего процессов? Магия?

UPDATE1: добавлена информация о том, что сценарий, возможно, был разработан в ksh, в то время как я использую bash.
UPDATE2: Добавлена проверка для проверки $PATH.

UPDATE3: сценарий говорит, что он написан для ksh, но он работает в bash. В ответ на ответ Кенстера я обнаружил, что бежит bash -posix . B . B не работает в командной строке. Это указывает на то, что разница в средах между командной строкой и скриптом заключается в том, что последний работает в режиме bash в режиме, совместимом с POSIX, тогда как в командной строке нет. Посмотрев немного ближе, я вижу это на странице bash man:

Когда вызывается как sh, bash переходит в режим posix после чтения файлов запуска.

shebang для A действительно #!/bin/sh.

В заключение, когда я запускаю A без синтаксиса пространственного пространства, он разворачивается к своей подоболочке, которая находится в режиме POSIX-совместимого режима, потому что shebang - это #!/bin/sh (вместо, например, #!/bin/bash. является критическим различием между средами командной строки и сценариев, которые приводят к тому, что A не может найти B

Ответ 1

Давайте начнем с того, как работает путь команды и когда он используется. Когда вы запускаете команду, например:

ls /tmp

Здесь ls не содержит символа /, поэтому оболочка ищет каталоги в вашем пути к команде (значение переменной среды PATH) для файла с именем ls. Если он находит один, он выполняет этот файл. В случае с ls он обычно находится в /bin или /usr/bin, и оба этих каталога обычно находятся на вашем пути.

Когда вы выдаете команду с/в командном слове:

/bin/ls /tmp

Оболочка не ищет путь к команде. Он выглядит специально для файла /bin/ls и выполняет это.

Запуск ./A - пример запуска команды с именем /. Оболочка не ищет путь к команде; он выглядит специально для файла с именем ./A и выполняет это. "" является сокращением для вашего текущего рабочего каталога, поэтому ./A относится к файлу, который должен находиться в вашем текущем рабочем каталоге. Если файл существует, он запускается как любая другая команда. Например:

cd /bin
./ls

будет работать для запуска /bin/ls.

Бег . A . A - пример поиска файла. Файл должен быть текстовым файлом, содержащим команды оболочки. Он выполняется текущей оболочкой без запуска нового процесса. Файл, который будет найден, найден таким же образом, как и команды. Если имя файла содержит /, то оболочка считывает определенный файл, который вы назвали. Если имя файла не содержит /, то оболочка ищет его в пути к команде.

. A        # Looks for A using the command path, so might source /bin/A for example
. ./A      # Specifically sources ./A

Таким образом, ваш скрипт пытается выполнить . B . B и не заявляет, что B не существует, хотя там есть файл с именем B прямо в вашем текущем каталоге. Как обсуждалось выше, оболочка искала бы ваш командный путь для B потому что B не содержал никаких символов. При поиске команды оболочка не выполняет автоматический поиск текущего каталога. Он ищет только текущий каталог, если этот каталог является частью пути к команде.

Короче говоря . B . B, вероятно, не работает, потому что у вас нет "." (текущий каталог) в вашем пути к команде, а скрипт, пытающийся установить источник B, предполагает, что "." является частью вашего пути. На мой взгляд, это ошибка в скрипте. Многие люди бегут без "." на их пути, и сценарий не должен зависеть от этого.

Редактировать:

Вы говорите, что сценарий использует ksh, в то время как вы используете bash. Ksh следует стандарту POSIX - фактически, KSH является основой стандарта POSIX и всегда ищет путь к команде, как я описал. У Bash есть флаг под названием "Режим POSIX", который контролирует, насколько строго он соответствует стандарту POSIX. Если не в режиме POSIX - как это обычно используют люди, bash проверяет текущий каталог для файла, который будет использоваться, если он не найдет файл в пути к команде.

Если вы должны запустить bash -posix и запустить . B . B в этом примере bash, вы должны обнаружить, что это не сработает.