shebang or not shebang

Вы должны заключать строки в кавычки с пробелами при использовании sed ( или большинство других инструментов) из командной строки. И поскольку вы уже используете двойные кавычки, вам нужно использовать одинарные кавычки:

echo '"GET /images/loading.gif HTTP/1.1" 200 10819 "https://...' | \
     sed 's|HTTP/1.1" 200.*|HTTP/1.1" 200|'

дает:

"GET /images/loading.gif HTTP/1.1" 200
4
08.05.2019, 09:35
5 ответов

Только что понял, что следующая переменная среды делает все это :$_

При запуске с использованием его значение равно './'

При запуске с использованием его значением является полный путь к .

В моем случае все просто:

#!/bin/bash

how_called=$_

if [[ "X$how_called" == X$0 || "X$how_called" ==X$BASH ]]; then
#                              ^in this case, if the login shell is not bash
   shebang=0
else
   shebang=1
fi

bn=$(basename $0)

Чуть позже (для моей цели):

if (( shebang == 1 )) || [[ ! -z $1 && "X$1" != X-* && "X$1" == X*\.${bn:0:3} && -x $1 ]]; then 
   # ^ shebang: first argument is the script file
   #                        ^ or not shebang: first argument **may** be a script file name
   #                                                    ^ ensure that this is a script by script extension
   #                                                       (otherwise just use the more verbose but standard --script=...)

   shebang_fn="$1"
   shift 1
   set -- --script="$shebang_fn" "$@" # fall back on standard way.
fi

(Я знаю, что здесь я немного переворачиваю таблицу, и нам все еще нужно убедиться, что это переносимое решение ).

0
27.01.2020, 20:44

Now, I need to know when blabla is called using the shebang, or not:

В C вы можете получить эту информацию через getauxval(AT_EXECFN), которая сообщит вам имя исходного исполняемого файла (, то есть первый аргумент, переданный вexecve(2))[1].

Но эта строка помещается в память сразу после аргументов командной строки и строк среды, в конце [stack]области памяти, поэтому ее можно получить непосредственно оттуда.

Например, следующий perl-скрипт (назовите его foo.pl), если сделать его исполняемым с chmod 755 foo.pl, будет напечатано ./foo.plпри прямом запуске и /usr/bin/perlпри запуске какperl./foo.pl:

#! /usr/bin/perl

open my $maps, "/proc/self/maps" or die "open /proc/self/maps: $!";
my $se;
while(<$maps>){ $se = hex($1), last if /^\w+-(\w+).*\[stack\]$/ }
open my $mem, "/proc/self/mem" or die "open /proc/self/mem: $!";
sysseek $mem, $se - 512, 0;
sysread $mem, $d, 512 or die "sysread: $!";
print $d =~ /([^\0]+)\0+$/, "\n";

В более новых ядрах (>=3.5 )linux конец среды также доступен в/proc/PID/stat(в 51-м поле, как описано на справочной страницеproc(5)).

#! /usr/bin/perl

open my $sh, "/proc/self/stat" or die "open /proc/self/stat: $!";
my @s = <$sh> =~ /\(.*\)|\S+/g;
open my $mem, "/proc/self/mem" or die "open /proc/self/mem: $!";
seek $mem, $s[50], 0;
$/ = "\0";
my $pn = <$mem> or die "readline: $!"; chomp $pn; print "$pn\n";

[1] Ядра Linux новее 2.6.26 представили запись вспомогательного вектора, указывающую на него (см. коммит ), но имя исполняемого файла было доступно в конце стека задолго до этого (, поскольку Linux -2.0 от 1996 ).

5
27.01.2020, 20:44

Настоящая проблема заключается в том, как вы разработали синтаксис командной строки <mypgm>. Вместо того, чтобы пытаться поддерживать два способа интерпретации его аргументов, вместо этого предоставьте два способа его вызова.

Команды Shebang предназначены для сценариев, которые выполняют содержимое вашего сценария; это может быть bash, perlили что-то еще, но ожидается, что он вызывается с именем файла сценария для выполнения. Как bashэто делает? Это не угадывается. Если он встречает какой-либо аргумент, который не похож на параметр (или аргумент параметра ), он рассматривает его как сценарий, который необходимо выполнить; аргументы после этого передаются сценарию. Например:

/bin/bash -x -e somename foo bar

Здесь bash будет искать файл somenameи пытаться запустить его как скрипт с аргументами fooи bar. Вы должны сделать то же самое, потому что вы возможно захотите когда-нибудь написать <mypgm> <myscript>в командной строке.

Если вы хотите, чтобы сценарий -меньше использования <mypgm>использовался по умолчанию, вы можете потребовать передачи сценария с <mypgm> -f <myscript>. Вот как это делает sed. Затем вы использовали бы его в строке shebang, подобной этой:

#!<mypgm> -f

Если вы хотите, чтобы сценарий использовался по умолчанию, как в случае с bashи perl, создайте параметр, который говорит: «На этот раз сценария нет». Вы можете использовать --для этого, чтобы <mypgm> -- one two threeне пытался запуститьone(или что-то еще )как скрипт.В этом случае строка shebang будет просто читать:

#!<mypgm>
9
27.01.2020, 20:44

У вас может быть обычная calcпрограмма с использованием какcalc PI + 3(и как расширениеcalc -f script_file_name).

Для использования в shebang create link (работают только жесткие ссылки, если я правильно помню )с именем, например. calcf, а затем в calcпрограмма проверяет имя исполняемого файла (для C/C++, смотрите argv[0]в функцииmain). Теперь у вас есть #! /some/path/calcfв сценариях.

Таким образом, вы избегаете использования таких параметров, как -cв командной строке (3 нажатия клавиш сохранены )и вам не нужны параметры в shebang (, которые могут быть проблематичными, как в комментарии Скотта shebang или не шебанг).

2
27.01.2020, 20:44

Возможно, я нашел что-то более близкое к решению:

cat /proc/$$/cmdline | tr '\0' '\n'

Вызывается из командной строки, вывод:

bash
<path to mypgm>
<myscript>

Звонили из Шебанга:

bash
<path to mypgm>
./<myscript>

Третья строка отличается.

Приведенное ниже решение все еще является эвристическим, а не окончательным. Действительно, как упомянули здесь несколько человек, игра с определенной опцией либо в режиме shebang (-f ), либо в режиме командной строки (-c... )будет на 100% пуленепробиваемой (жесткая ссылка решение тоже ).

Однако это решение не подходит для возникшей ситуации. Более того, оба решения НЕ являются взаимоисключающими. Вы можете либо полагаться на приведенную ниже эвристику при отсутствии параметров -f и -c, либо на надежное решение, если вы используете один из них.

Эвристический эквивалент в bash.

    #!/bin/bash

    # first statement for more accuracy
    shebang=$(</proc/$$/status)

    shebang=$(echo "${shebang// /\n}" \
       | awk '$1 ~ /^nonvoluntary_ctxt_switches:$/ {print $2}')

    maybe_file=$(awk -v RS="\0" 'NR==3' /proc/$$/cmdline)

    if    [[ "X$maybe_file" == X*/* ]] \
       && [[ maybe_file != X-* ]] \
       && (( shebang > 1 )) \
       && [[ -x "$maybe_file" ]]; then
        shebang=1
    else
        shebang=0
    fi

Понижение вероятности даже до очень низкой вероятности в нехорошем варианте (Я понимаю, что люди голосуют против этого ), но смешивание этой эвристики с пуленепробиваемым решением может быть (или нет )лучше, чем ничего, пока не будет найдено более окончательное решение.

Я прекрасно понимаю, что происходит, плюсы и минусы каждого предоставленного комментария(Всем большое спасибо!). Я просто немного удивлен, что, по-видимому, нет возможности получить исходную командную строку после шебанга.

-1
27.01.2020, 20:44

Теги

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