bash: Деякі проблеми під час використання прочитаного <<< “$ 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

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

Вище ми бачимо, у який файл записується ваша командна послідовність.


1
Не «створювати дескриптори файлів» (це не має сенсу). Для створення файлу . Це не readте, що відкриває файл для запису (це було б нерозумно), це <<<.
Жил "ТАК - перестань бути злим"

@Gilles - дякую, я не зовсім зрозумів, що це мені говорить. Розчистили A.
slm

Велике спасибі! Дуже приємна методика, яка може навіть допомогти мені кілька разів у майбутньому з подібними проблемами. Тим НЕ менше, одна річ , це турбує мене, і той факт , що /tmpце жорстко шлях. І , напевно , ви вже здогадалися, /tmp IS вже там, але тільки для читання , як добре! А оскільки робота над цією консоллю відновлення дозволить мені увійти до моєї файлової системи в реальному часі , я не хотів би там возитися, посилаючись на щось подібне (навіть не перебуваючи на цій консолі).
синтаксичний помилок

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 = '' .
синтаксичний помилок
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.