Основная идея заключается в том, что VAR=VALUE some-command
устанавливает VAR
в VALUE
для выполнения some-command
, когда some-command
является внешней командой. Если вы объедините эту интуицию с некоторыми знаниями о том, как работает оболочка, вы должны прийти к правильному ответу в большинстве случаев. Ссылка на POSIX - "Простые команды" в главе "Язык команд оболочки".
Если some-command
является внешней командой, VAR=VALUE some-command
эквивалентен env VAR=VALUE some-command
. VAR
экспортируется в окружение some-command
, и его значение (или отсутствие значения) в оболочке не меняется.
Если some-command
является функцией, то VAR=VALUE some-command
эквивалентно VAR=VALUE; some-command
, т.е. присваивание остается на месте после возврата функции, а переменная не экспортируется в среду. Причина этого связана с конструкцией оболочки Bourne (и впоследствии с обратной совместимостью): в ней не было средств для сохранения и восстановления значений переменных после выполнения функции. Отсутствие экспорта переменной имеет смысл, поскольку функция выполняется в самой оболочке. Однако ksh (включая ATT ksh93 и pdksh/mksh), bash и zsh реализуют более полезное поведение, когда VAR
устанавливается только во время выполнения функции (она также экспортируется). В ksh это делается, если функция определена с синтаксисом ksh function NAME ...
, а не если она определена со стандартным синтаксисом NAME ()
. В bash это делается только в режиме bash, но не в режиме POSIX (при запуске с POSIXLY_CORRECT=1
). В zsh это делается, если не установлена опция posix_builtins
; эта опция не установлена по умолчанию, но включается с помощью emulate sh
или emulate ksh
.
Если some-command
является встроенным модулем, поведение зависит от типа встроенного модуля. Специальные встроенные модули ведут себя как функции. Специальные встроенные модули - это те, которые должны быть реализованы внутри оболочки, поскольку они влияют на состояние оболочки (например, break
влияет на поток управления, cd
влияет на текущий каталог, set
влияет на позиционные параметры и опции...). Другие встроенные модули встроены только для производительности и удобства (в основном - например, функция bash printf -v
может быть реализована только встроенным модулем), и они ведут себя как внешняя команда.
Присвоение происходит после расширения псевдонима, поэтому если some-command
является псевдонимом, сначала расширьте его, чтобы узнать, что произойдет.
Обратите внимание, что во всех случаях присваивание выполняется после разбора командной строки, включая любую подстановку переменных в самой командной строке. Так var=a; var=b echo $var
печатает a
, потому что $var
оценивается до того, как происходит присваивание. И таким образом IFS=. printf "%s\n" $var
использует старое значение IFS
для разделения $var
.
Я рассмотрел все типы команд, но есть еще один случай: когда нет команды для выполнения, т.е. если команда состоит только из присваиваний (и, возможно, перенаправлений). В этом случае присваивание остается на месте. VAR=VALUE OTHERVAR=OTHERVALUE
эквивалентен VAR=VALUE; OTHERVAR=OTHERVALUE
. Поэтому после IFS=. arr=($var)
, IFS
остается установленным на .
. Поскольку вы могли использовать $IFS
в присваивании arr
с расчетом на то, что оно уже имеет свое новое значение, имеет смысл, что новое значение IFS
используется для расширения $var
.
В целом, вы можете использовать IFS
только для временного разделения полей:
third=$(IFS=. ; set -f; set -- $var; echo "$3")
является сложным способом выполнения third=${var#*.*.}
за исключением того, что они ведут себя по-разному, когда значение var
содержит менее двух .
символов);IFS=. some-function
, где some-function
определяется с помощью синтаксиса ksh function some-function ...
;IFS=. some-function
, пока они работают в родном режиме, а не в режиме совместимости. Нет. Когда nmap
сканирует несколько IP-адресов, отображаются отдельные списки портов. Он не объединяет результаты с разных IP-адресов. Сравните результатnmap 127.0.0.1-2
(или nmap 127.0.0.1 127.0.0.2
).
nmap 0.0.0.0
эквивалентно nmap 127.0.0.1
. По крайней мере, для программного обеспечения, которое вы используете.
Помните, что когда вы запускаете nmap
от имени пользователя root
, по умолчанию используется другой метод сканирования. Например, это то, что позволяет ему сканировать «порт 0». Однако, если он не запущен от имени пользователя root, «Nmap запрашивает базовую операционную систему установить соединение с целевой машиной и портом, выполнив системный вызов connect».
Дело в том, что я забыл об этой разнице :-), поэтому я пошел и отследил используемую вами операционную систему, то есть Linux. Я смотрел на это раньше, ха-ха. Это поведение не является частью официальной документации для Linux.Как правило, лучше использовать 127.0.0.1
, который задокументирован и является стандартным для всех реализаций IPv4.
Вы можете отследить tcp _v4 _подключение через конкретное условие:
if (!fl4->daddr) {
fl4->daddr = fl4->saddr;
if (!fl4->daddr)
fl4->daddr = fl4->saddr = htonl(INADDR_LOOPBACK);
dev_out = net->loopback_dev;
fl4->flowi4_oif = LOOPBACK_IFINDEX;
res->type = RTN_LOCAL;
flags |= RTCF_LOCAL;
goto make_route;
}
Это говорит о том, что в Linux nmap -sT 0.0.0.0
эквивалентно nmap -sT 127.0.0.1
.
Кроме того, nmap -sT 0.0.0.0 -S 192.168.1.97
будет эквивалентноnmap -sT 192.168.1.97
:-). (Допустим, ваш IP-адрес 192.168.1.97 ). Если вы дочитали до этого места, можете попробовать сами :-).
Опять же, при работе от имени пользователя root тип сканирования по умолчанию будет , а не использовать вызов операционной системы connect ()для подключения к каждому TCP-порту. Вместо этого nmap будет «отправлять и получать необработанные TCP-пакеты». Таким образом, вы полностью полагаетесь на код nmap для генерации пакетов и принятия собственных решений. Возможно, что nmap не будет генерировать те же пакеты, что и ОС. Таким образом, sudo nmap 0.0.0.0 -S 192.168.1.97
может не давать тех же результатов, что и sudo nmap 192.168.1.97
. Хотя может и получится. Не знаю, я не пробовал.