Как сценарий ksh может определить полный путь к себе, если он получен от другого? - PullRequest
5 голосов
/ 01 октября 2011

Как скрипт может определить свой путь, если он получен из ksh?то есть

$ ksh ". foo.sh"

Я видел очень хорошие способы сделать это в BASH, опубликованном в stackoverflow и в других местах, но еще не нашел метод ksh.

Использование "$ 0" неРабота.Это просто относится к «ksh».

Обновление: я пытался использовать команду «history», но не знает историю вне текущего скрипта.

$ cat k.ksh
#!/bin/ksh
. j.ksh
$ cat j.ksh
#!/bin/ksh
a=$(history | tail -1)
echo $a
$ ./k.ksh
270 ./k.ksh

Iхотел бы это эхо "* ./j.ksh".

Ответы [ 4 ]

5 голосов
/ 01 апреля 2014

Если это AT & T ksh93, эта информация сохраняется в пространстве имен .sh, в переменной .sh.file.

Пример

sourced.sh:

(
 echo "Sourced: ${.sh.file}"
)

Вызов:

$ ksh -c '. ./sourced.sh'

Результат:

Sourced: /var/tmp/sourced.sh

Переменная .sh.file отличается от $0.Хотя $0 может быть ksh или /usr/bin/ksh или именем запущенного в данный момент сценария, .sh.file всегда будет ссылаться на файл для текущей области.

В интерактивной оболочке эта переменная даже не существует:

$ echo ${.sh.file:?}
-ksh: .sh.file: parameter not set
1 голос
/ 16 октября 2014

Разница, конечно, между источником и разветвлением заключается в том, что источник приводит к тому, что вызываемый сценарий выполняется в вызывающем процессе.Хенк показал элегантное решение в ksh93, но если, как и я, вы застряли на ksh88, то вам нужна альтернатива.Я бы не стал менять метод поиска по умолчанию ksh с использованием синтаксиса C-shell, и на работе это противоречило бы нашим стандартам кодирования, поэтому создание и использование функции source () для меня было бы неработоспособным.ps, $ 0 и $ _ ненадежны, поэтому есть альтернатива:

$ cat b.sh;кошка c.sh;./b.sh

#!/bin/ksh
export SCRIPT=c.sh
. $SCRIPT 
echo "PPID: $$"
echo "FORKING c.sh"
./c.sh

Если мы установим вызываемый скрипт в переменную и создадим его с помощью переменной, эта переменная будет доступна для вызываемого скрипта, поскольку они находятся в одном пространстве процесса.

#!/bin/ksh
arguments=$_
pid=$$
echo "PID:$pid"
command=`ps -o args -p $pid | tail -1`
echo "COMMAND (from ps -o args of the PID): $command"
echo "COMMAND (from c.sh's \$_ ) : $arguments"
echo "\$SCRIPT variable: $SCRIPT"
echo dirname: `dirname $0`
echo ; echo

Вывод выглядит следующим образом:

PID:21665
COMMAND (from ps -o args of the PID): /bin/ksh ./b.sh
COMMAND (from c.sh's $_ ) : SCRIPT=c.sh
$SCRIPT variable: c.sh
dirname: .


PPID: 21665
FORKING c.sh
PID:21669
COMMAND (from ps -o args of the PID): /bin/ksh ./c.sh
COMMAND (from c.sh's $_ ) : ./c.sh
$SCRIPT variable: c.sh
dirname: .

Таким образом, когда мы устанавливаем переменную SCRIPT в скрипте вызывающего абонента, переменная либо доступна из операндов исходного скрипта, либо вВ случае разветвленного процесса переменная вместе со всеми другими переменными среды родительского процесса копируется для дочернего процесса.В любом случае переменная SCRIPT может содержать вашу команду и аргументы и будет доступна как в случае получения, так и разветвления.

1 голос
/ 03 октября 2011

Я считаю, что единственное переносимое решение - переопределить команду источника:

source() {
  sourced=$1
  . "$1"
}

, а затем использовать источник вместо.(имя скрипта будет в $ sourced).

0 голосов
/ 01 октября 2011

Вы должны найти его как последнюю команду в истории.

...