Нет, строка в bash не может содержать NUL ( \ 0
).
Следовательно, переменная (поскольку она содержит строку) не может содержать NUL.
Причина в том, что bash написан с парадигмой c
«строка заканчивается на NUL». [1] Ядро Linux также накладывает такое ограничение. [2] Но даже если бы ядро позволяло использовать NUL в строках [3] (аргументы), большинство оболочек и, в частности, bash не могли включать NUL внутри переменных [4].
Позиционные параметры ( $ 1
, $ 2
и т. Д.) Эквивалентны переменным и также не могут содержать NUL.
Однако пустые значения могут существовать в файлах, в потоках и в printf:
$ printf 'test\0nuls\n' | od -vAn -tx1c
74 65 73 74 00 6e 75 6c 73 0a
t e s t \0 n u l s \n
Как вы можете видеть, printf создает NUL и проходит через конвейер ( |
). {{1} } Но NUL удаляются из «выполнения команд»:
$ echo $(printf 'test\0nuls\n') | od -vAn -tx1c
bash: warning: command substitution: ignored null byte in input
74 65 73 74 6e 75 6c 73 0a
t e s t n u l s \n
В bash 4.4 он даже выдает предупреждение.zsh, в этом случае незаметно замените NUL пробелом:
$ zsh -c ' echo $(printf "test\0nuls\n") | od -vAn -tx1c'
74 65 73 74 20 6e 75 6c 73 0a
t e s t n u l s \n
Мы можем создать файл, содержащий NUL, с помощью printf и либо cat
, head
, tail
] или dd часть файла, которая включает NUL:
$ printf 'test\0nuls\0in\0files\0\n' > testnul.bin
$ cat testnul.bin | xxd -ps
74657374006e756c7300696e0066696c6573000a
$ head -c 7 testnul.bin | xxd -ps
74657374006e75
$ dd if=testnul.bin bs=7 count=1 | xxd -ps
74657374006e75
1+0 records in
1+0 records out
7 bytes copied, 0.000655689 s, 10.7 kB/s
$ dd if=testnul.bin bs=7 count=1 2>/dev/null| xxd -ps
74657374006e75
В вашем случае не существует простого [5] способа использовать содержимое двоичного файла в качестве аргумента. Может быть, шестнадцатеричное представление могло бы сработать:
$ myProgram "$parameter1" "$(xxd -ps -c 512 binaryFile.dd)"
Спасибо @Gilles за всю дополнительную работу (и детали) ниже.
[1]
Все сводится к старому определению строки C
, что «строки заканчиваются на NUL ( \ 0
)». {{1} } Эта парадигма была закодирована в нескольких C
библиотеках и инструментах, несколько примеров которых есть в POSIX. Подобно strcpy
здесь , в котором говорится (выделено мной):
Функция strcpy () копирует строку, на которую указывает s2 (, включая завершающий символ NUL ), в массив, на который указывает s1.
Это означает, что предполагается, что строка заканчивается NUL.
Или, другими словами, может быть только один NUL, последний.
[2] Системный вызов execve ()
, также определенный в POSIX , ожидает, что строки (аргументы команды) оканчиваются на NUL. Вот почему даже оболочки, которые могут работать с NUL (большинство из них не работают, за исключением zsh):
$ zsh -c 'a=$(printf "included\0null"); printf "$a"' | od -vAn -tx1c
69 6e 63 6c 75 64 65 64 00 6e 75 6c 6c
i n c l u d e d \0 n u l l
Может not использовать NUL в аргументах, передаваемых execve ()
call:
$ zsh -c 'a=$(printf "included\0null"); /usr/bin/printf "$a"' | od -vAn -tx1c
69 6e 63 6c 75 64 65 64
i n c l u d e d
[3] Но даже если ядро может включать NUL в аргументы, bash не разрешит их:
$ bash -c 'a=$(printf "included\0null"); /usr/bin/printf "$a"' | od -vAn -tx1c
bash: warning: command substitution: ignored null byte in input
69 6e 63 6c 75 64 65 64 6e 75 6c 6c
i n c l u d e d n u l l
В bash 4.4 он даже выдает предупреждение при удалении NUL.
[4] Большинство командных интерпретаторов, и, в частности, bash, не могли включать NUL внутри переменных.
$ printf 'included\0null' | od -vAn -tx1c
69 6e 63 6c 75 64 65 64 00 6e 75 6c 6c
i n c l u d e d \0 n u l l
$ printf 'included\0null' | ( read a; printf '%s\n' "$a" | od -vAn -tx1c )
69 6e 63 6c 75 64 65 64 6e 75 6c 6c
i n c l u d e d n u l l
Если запущена оболочка zsh, это (вместо этого) будет работать с нулем:
$ zsh -c 'printf "included\0null" | ( read a; printf "%s\n" "$a" | od -vAn -tx1c )'
69 6e 63 6c 75 64 65 64 00 6e 75 6c 6c 0a
i n c l u d e d \0 n u l l \n
[5]
Это означает, что «прямое» (простое) включение байта со значением 0 ( \ 0
) невозможно. Но закодированный (сложный), используя C-строку $ '\ 0'
, в шестнадцатеричном формате, с основанием 64 или в каком-либо эквиваленте, может быть включено значение нуля.
Последнее обновление: Эта проблема возникла на одной старой машине, которая сообщала об ошибках носителя («битые сектора») в корневой файловой системе. Диск вполне может умереть, поэтому я эвакуировал свои файлы. На других машинах с Fedora 25 эта проблема не возникала.
Уроки:
id -a
) и группами, применяемыми при следующем входе в систему ( id -a "$ USER"
). Обновление : Я отправил это в систему отслеживания ошибок Fedora: Открытие пользователей Gnome немедленно удаляет меня из группы wheel (доступ sudo)!
Мой пользователь больше не в группе wheel
:
$ id alan-sysop
uid=1000(alan-sysop) gid=1000(alan-sysop) groups=1000(alan-sysop),1002(sysnote),1003(sshlogin)
Когда-то во время моего сеанса мой пользователь был удален из группы wheel
.
Я обязательно повторно добавил себя (до того, как закончил сеанс!)
sudo usermod -a -G wheel alan-sysop
Во время сеанса я выполнил sudo usermod -a -G sshlogin alan-sysop
. Я не попал в обычную ловушку, забывая -a
в команде usermod
. Во-первых, я вижу, что прошел -a
. Кроме того, я оставался членом группы sysnote
; если бы я забыл -a
, то это тоже было бы удалено.
Это оставляет одну возможность: я также открыл панель настроек Gnome Users.
Возможно, я ввел свой пароль для аутентификации (чтобы внести изменения в пользователей), а затем неправильно щелкнул кнопку типа учетной записи «Стандартный», не осознавая этого?
НЕТ. Открытие страницы настроек Gnome Users и ввод моего пароля немедленно удаляет моего пользователя из группы wheel! Вздох.