bash: некоторые проблемы при использовании read <<< «$ VARIABLE» в корневом разделе только для чтения. Любые известные обходные пути?

11

Просто по стечению обстоятельств мне пришлось использовать свой скрипт ATA-ID-имя-устройства (находится здесь: /server/244944/linux-ata-errors-translating-to-a-device-name/ 426561 # 426561 ) в разделе только для чтения/ . Если вам интересно, это была консоль восстановления Ubuntu, которая позволит вам получить доступ к вашему /разделу, но по умолчанию будет монтировать его только для чтения. Я рад этому, потому что иначе я, вероятно, никогда бы не узнал, что мой скрипт ведет себя странно в системе R / O из-за определенной строки, вот этой:

IFS=: read HostMain HostMid HostSub <<< "$HostFull"

Это не работает, если нет разрешения на запись. Я не предполагал, что это потерпит неудачу. Но , видимо, <<<оператор действительно требует , чтобы написать некоторый временный файл где - нибудь.

Но есть ли способ обойти создание временного файла или есть способ указать, куда файл записывается? В консоли восстановления Ubuntu, как ни странно, есть разрешение на запись в /runкаталог, так что это было бы возможно, если бы я мог как-то «сказать» readзаписать временный файл в другое место, чем обычно.

ошибка синтаксиса
источник
2
@gniourf_gniourf Нет, «открытие дескриптора файла» не будет проблемой (с чего бы это?) и не /dev/fdимеет к этому никакого отношения. <<<это виновник, потому что он создает временный файл (который должен быть где-то записан).
Жиль "ТАК - перестать быть злым"

Ответы:

8

Массив может выполнять разбор строки без необходимости во временном файле. Не забудьте отключить тряску

set -f
IFS=: Hosts=($HostFull)
HostMain=${Hosts[0]}
HostMid=${Hosts[1]}
HostSub=${Hosts[2]}
set +f
XAE
источник
2
или даже без IFS, если вы не уверены , что там нет места в $HostFullкачестве так: Hosts=( ${HostFull//:/ } ). Или даже если есть пробелы: HostMain=${HostFull%%:*}; HostMid=${HostFull#*:}; HostSub=${HostMid#*:}; HostMid=${HostMid%:*}(или что-то подобное, я запутался :D).
gniourf_gniourf
Вы правы, когда вы показываете, что расширение параметров - это сложное дело ...
xae
4

Я согласен с @gniourf_gniourf, вам, вероятно, нужен доступ для записи, но не к файловым дескрипторам, скорее всего, к файлу.

Вы можете проверить это, отследив выполнение вашей команды в разделе только для чтения.

{ strace -p "$$" & sleep 1; read var1 <<< "hi"; sleep 1; kill "$1"; }

Выше будет работать straceна оболочке Bash (процесс $$). Затем он спит в течение 1 секунды, а затем запускается readиз ЗДЕСЬ. Я положил строку "hi"в этой позиции. Я тогда еще sleepна один второй и затем .killstrace

пример

При анализе этого вывода вы заметите, что файл открывается как O_WRONLY, что для записи в файл.

open("/tmp/sh-thd-4137571604", O_WRONLY|O_CREAT|O_EXCL|O_TRUNC, 0600) = 3

Выше мы можем видеть, в какой файл записывается ваша последовательность команд.

SLM
источник
1
Не «создавать файловые дескрипторы» (это не имеет никакого смысла). Создать файл . Это не readто, что открывает файл для записи (это было бы глупо), это <<<.
Жиль "ТАК - перестать быть злым"
@ Жиль - спасибо, я не совсем понял, что это говорит мне. Убрал А.
СЛМ
Большое спасибо! Очень хорошая техника, которая может даже помочь мне многократно в будущем с подобными проблемами. Тем не менее, одна вещь , это беспокоит меня, и тот факт , что /tmpэто жёстко путь. И , наверное , вы уже догадались, /tmp IS уже там, но только для чтения , как хорошо! И поскольку работа с этой консолью восстановления приведет к тому, что я войду в свою живую файловую систему, я бы не хотел вмешиваться в нее с помощью символических ссылок или чего-либо еще (даже в этой консоли).
syntaxerror
3

Я считаю, что позиционные параметры очень полезны для такого рода задач. Как правило, он также переносим на все оболочки и не требует ни вилок, ни временных файлов.

$ HostFull=main:mid:sub    
$ oldIFS=$IFS; IFS=:; set -- $HostFull; IFS=$oldIFS
$ echo $1
main
$ echo $2
mid
$ echo $3
sub
Дэвид Сэйнти
источник
Хороший подход! Спасибо. Кроме того, мне нравится, что для этого не требуются какие-либо внешние инструменты (которые мы обычно не ожидаем найти в этих ограниченных средах в любом случае). Единственное , что может вызвать некоторые проблемы есть $1, $2, $3материал: помните , что в сценарии, это, как правило , стоит за аргумент , переданного в сценарий самого . - И пока мы на этом: если IFS должен быть пробелом, * IFS = * не будет использоваться в этом синтаксисе; вам придется явно указать IFS = '' .
синтаксическая ошибка