Надежное определение пути к каталогу, содержащему запущенный скрипт

Вы попробовали synaptiks? Это - простая программа GUI, которая всегда решала любые проблемы с моей конфигурацией сенсорной панели.

Устанавливать:

sudo apt-get install kde-config-touchpad

Затем необходимо смочь выполнить его с

synaptiks && synaptiks

(первое synaptiks только помещает значок в системный лоток и не запускает GUI по некоторым причинам),

2
23.05.2017, 15:40
2 ответа

Есть эвристика, которые могут вам помочь, но нет полностью надежного способа.

Otheus показывает, как использовать файловые дескрипторы . Это хороший эвристический, который работает в большинстве случаев. Однако есть краевые случаи, когда это не удается, и нет способа обнаружить неудачи.

Пример: возьмите следующий скрипт.

#!/bin/sh
set
lsof -p$$ | sed 's/[0-9][0-9]*//'

Сделайте два копии скрипта, один под названием Foo , один под названием BAR . Теперь давайте немного подчеркнем:

$ env -i PATH=/bin:/usr/bin perl -MPOSIX -e 'dup2(4, 11) or die $!; exec "dash", "foo", "bar"' 3<foo 4<bar </dev/null >foo.out
$ env -i PATH=/bin:/usr/bin perl -MPOSIX -e 'dup2(3, 10) or die $!; exec "dash", "bar", "foo"' 3<foo 4<bar </dev/null >bar.out
$ diff foo.out bar.out

17C17

Dash Gilles 1w Reg 0,24 99 10130022 /tmp/202954/bar.out

The Только разница вот файл, в котором я зарегистрировал вывод.

Еще один случай, когда этот эвристический потерпит неудачу, это если оболочка вызвана на стандартном входе или с -C .

Другой подход - анализ командной строки оболочки. На Linux вы можете получить доступ к нему через / proc . Аргументы NULL-DELIMITED, которые трудно разбираться с портативными инструментами оболочки (недавние инструменты GNU облегчают), но это может быть сделано. Портативно, вам нужно позвонить PS для доступа к аргументам, и нет никакого вывода формата, который однозначен: PS -O args объединяет аргументы пробелами и могут быть усечены.

Даже в Linux проблема, в которой вы столкнетесь с вот, заключается в том, что оболочка может быть вызвана параметрами, которые ваш сценарий не знает, и один из этих вариантов может возникнуть аргумент. Например, предположим, что у вас есть скрипт 1 и другой скрипт, называемый 2 .

mksh -T 1 2

Это вызывает MKSH на / dev / tty1 и запускает скрипт 2 .

zsh -T 1 2

Это вызывает ZSH с вариантом CPRecedence и запускает скрипт 1 с аргументом 2 .

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

1
27.01.2020, 22:00

Я собираюсь нанести удар первой ступени. Кто-нибудь другой, надеюсь, улучшит.

Перед выполнением вашего скрипта оболочка откроет файл-дизайнер к файлу. Обычно это назначается по fd 255. В любом случае, если есть открытый fd, то lsof может его найти. Поэтому мы используем lsof -p $$ и получаем имя файла самого высокого файла-диспетчера. lsof не будет работать с каждым вкусом unix. Вики для BSD говорит, что эквивалент есть fstat. Похоже, что это на Darwin (Mac OS). С `-F

Пример скрипта:

#!/bin/sh

this_script_path=`lsof -p $$  | awk '/\/'${0##*/}'$/' | cut -c 55-`

Очевидно, что вырезание очень зависит от специфического форматирования lsof. Мы можем облегчить это в версии 2. Кстати: Моя версия lsof переводит непечатаемые символы так, что даже вкладки в именах путей преобразуются в \t.

Версия 2. Прошу прощения за некрасивый код perl. На этот раз мы будем использовать опцию -F для управления выводом. С помощью -Fn мы получим такой вывод:

p3834
fcwd
n/home/joe/test
frtd
n/
ftxt
n/bin/bash
fmem
n/lib64/ld-2.12.so
fmem
n/lib64/libdl-2.12.so
fmem
n/lib64/libc-2.12.so
fmem
n/lib64/libtinfo.so.5.7
fmem
n/usr/lib/locale/locale-archive
fmem
n/usr/lib64/gconv/gconv-modules.cache
f0
n/dev/pts/1
f1
n/dev/pts/1
f2
n/dev/pts/1
f255
n/home/joe/test/t.sh

Мы должны преобразовать этот беспорядок так, чтобы самым высоким файлом-дискадриптором (я предполагаю, что вы не можете полагаться на то, что это 255) было имя сценария. (Похоже, это работает и в тире dash.)

this_script_path=`lsof -p $$ -F fn | 
  perl -lane '
        $fd=$1,next if /^f(\d+)/; 
        $p{$fd}=$1 if $fd and /^n(.*)/;
        $fd="";
  }END { 
        @x=sort {$a<=>$b} keys %p;
        print $p{$x[-1]}; 
  }{'`

Скрипт на perl уродлив, я согласен. Это был один лайнер, который я разбил для ясности. Мы захватываем номер файла-дезкриптора, если строка начинается с f, и мы захватываем имя файла в хэш, если у нас есть действительный файл-дезкриптор и действительное имя файла. На всякий случай, если ни одно из этих условий не было выполнено, мы очищаем $fd. После обработки всех строк, мы численно сортируем ключи (наши файловые скрипторы) нашего хэша, сохраняем результаты в массиве x и выводим содержимое хэша p имен файлов, проиндексированных последним элементом (наибольшее значение) в массиве x.

Единственный вопрос: будет ли lsof установлен на всех системах и насколько стабилен этот формат вывода.

3
27.01.2020, 22:00

Теги

Похожие вопросы