bash: Niektóre problemy podczas używania odczytu <<< „$ VARIABLE” na partycji root tylko do odczytu. Jakieś znane obejścia?


11

Zbiegiem okoliczności musiałem użyć skryptu ATA-ID-na-nazwę-urządzenia (tutaj: /server/244944/linux-ata-errors-translating-to-a-device-name/ 426561 # 426561 ) na partycji tylko do odczytu/ . Jeśli jesteś ciekawy, była to konsola odzyskiwania Ubuntu, która pozwoli ci uzyskać dostęp do twojej /partycji, ale domyślnie zainstaluje ją tylko do odczytu. Cieszę się z tego, ponieważ w przeciwnym razie prawdopodobnie nigdy nie dowiedziałbym się, że mój skrypt zachowuje się dziwnie w systemie R / O z powodu określonej linii, tej:

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

To nie działa, jeśli nie ma uprawnień do zapisu. Jednak nie przypuszczałbym, że to zawiedzie. Ale najwyraźniej <<<operator nie musi gdzieś zapisać pliku tymczasowego.

Ale czy jest jakiś sposób na obejście tworzenia pliku tymczasowego, czy też istnieje sposób na określenie, gdzie plik jest zapisywany? W konsoli odzyskiwania Ubuntu istnieje --- dziwnie --- uprawnienie do zapisu w /runkatalogu, więc tak by się stało , gdybym mógł w jakiś sposób „powiedzieć”, readaby zapisać plik tymczasowy w innym miejscu niż zwykle.


2
@gniourf_gniourf Nie, „otwarcie deskryptora pliku” nie stanowiłoby problemu (dlaczego?) i /dev/fdnie ma z tym nic wspólnego. <<<jest jednak winowajcą, ponieważ tworzy plik tymczasowy (który gdzieś trzeba zapisać).
Gilles „SO- przestań być zły”

Odpowiedzi:


8

Tablica może parsować łańcuch bez potrzeby tworzenia pliku tymczasowego. Nie zapomnij wyłączyć globowania.

set -f
IFS=: Hosts=($HostFull)
HostMain=${Hosts[0]}
HostMid=${Hosts[1]}
HostSub=${Hosts[2]}
set +f

2
lub nawet bez IFS, jeśli jesteś pewien, że nie ma miejsca w $HostFulljak tak: Hosts=( ${HostFull//:/ } ). Lub nawet jeśli są spacje: HostMain=${HostFull%%:*}; HostMid=${HostFull#*:}; HostSub=${HostMid#*:}; HostMid=${HostMid%:*}(lub coś podobnego, jestem zdezorientowany :D).
gniourf_gniourf

Masz rację, ponieważ pokazujesz, że rozszerzanie parametrów jest trudne ...
XIII

4

Zgadzam się z @gniourf_gniourf, prawdopodobnie potrzebujesz dostępu do zapisu, ale nie do deskryptorów plików, najprawdopodobniej pliku.

Możesz to sprawdzić, śledząc wykonanie polecenia na partycji tylko do odczytu.

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

Powyższe będzie działać stracena powłoce Bash (proces $$). Następnie śpi przez 1 sekundę, a następnie uruchamia readTUTAJ STRING. Ustawiłem sznurek "hi"w tej pozycji. I wtedy sleepdla jednego więcej sekundę, a następnie .killstrace

Przykład

Podczas analizowania tego wyniku zauważysz, że plik jest otwierany jako O_WRONLY, co służy do zapisu do pliku.

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

Powyżej możemy zobaczyć, do którego pliku jest zapisywana sekwencja poleceń.


1
Nie „tworzyć deskryptorów plików” (to nie ma sensu). Aby utworzyć plik . To nie readotwiera pliku do pisania (to byłoby głupie), to jest <<<.
Gilles „SO- przestań być zły”

@Gilles - dzięki, nie bardzo rozumiałem, co mi to mówi. Oczyścił A.
slm

Dziękuję Ci bardzo! Bardzo fajna technika, która może w przyszłości pomóc mi wiele razy z podobnymi problemami. Jednak jedno jest niepokojące mnie i to jest fakt, że /tmpjest ustalony tor. I pewnie zgadliście, /tmp JEST już tam, ale tylko do odczytu! A ponieważ praca nad tą konsolą odzyskiwania spowoduje, że zaloguję się do mojego systemu plików na żywo , nie chciałbym tam wchodzić przez połączenie symboliczne lub cokolwiek innego (nawet będąc w tej konsoli).
składniaerror

3

Uważam, że parametry pozycyjne są bardzo przydatne do tego rodzaju zadań. Zasadniczo jest również przenośny dla wszystkich powłok i nie kosztuje forksów ani plików tymczasowych.

$ HostFull=main:mid:sub    
$ oldIFS=$IFS; IFS=:; set -- $HostFull; IFS=$oldIFS
$ echo $1
main
$ echo $2
mid
$ echo $3
sub

Dobre podejście! Dziękuję Ci. Ponadto podoba mi się to, że nie wymaga żadnych zewnętrznych narzędzi (których zwykle nie można się spodziewać w tych ograniczonych środowiskach). Jedyną rzeczą, która może powodować pewne problemy jest $1, $2, $3materiał: należy pamiętać, że w skrypcie, to zwykle stoją za argument przekazany do skryptu samego . - A skoro już o tym mowa: jeśli IFS ma być spacją, * IFS = * nie zrobi tego w tej składni; musisz jawnie podać IFS = '' .
składniaerror
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.