BASH: поиск раздела из вывода diskutil

843
juliushibert

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

Я написал очень грязный oneliner, так как я не могу понять, как эффективно найти основной жесткий диск (предположительно всегда Macintosh HD), а затем выяснить, что такое раздел EFI на том же диске, и затем найти диск # s # ИДЕНТИФИКАТОР для раздела EFI на жестком диске Macintosh.

Стандартный вывод diskutil listпримерно такой

$ diskutil list /dev/disk0 #:                       TYPE NAME                    SIZE       IDENTIFIER 0:      GUID_partition_scheme                        *500.1 GB   disk0 1:                        EFI EFI                     209.7 MB   disk0s1 2:                  Apple_HFS Macintosh HD            499.1 GB   disk0s2 3:                 Apple_Boot Recovery HD             784.2 MB   disk0s3  /dev/disk1 #:                       TYPE NAME                    SIZE       IDENTIFIER 0:      GUID_partition_scheme                        *1.5 TB     disk1 1:                        EFI EFI                     209.7 MB   disk1s1 2:                  Apple_HFS Data                    1.5 TB     disk1s2 

Так что вот грязный лайнер, который я использовал. Есть ли лучший способ сделать это? 

diskutil mount $(diskutil list | grep -i 'Macintosh\ HD' | awk '' | grep -i 'disk0s')

1

3 ответа на вопрос

0
Yaron

You can try and detect the main block device by using:

mount | awk '/on \/ / '

I can't seem to find a way to detect my main volume since my output doesn't list them, I can only see the main block device and some description of the content:

/dev/disk0 #: TYPE NAME SIZE IDENTIFIER 0: GUID_partition_scheme *251.0 GB disk0 1: EFI EFI 209.7 MB disk0s1 2: Apple_CoreStorage 250.1 GB disk0s2 3: Apple_Boot Recovery HD 650.0 MB disk0s3 /dev/disk1 #: TYPE NAME SIZE IDENTIFIER 0: Apple_HFS Macintosh HD *249.8 GB disk1 Logical Volume on disk0s2 XXXXXXXX-XXXX-XXXX-XXXX-7C6C089FXXXX Unencrypted 

In my case I can easily use awk '/Logical Volume/ ' but a more robust script will take the Mac version into account to check all possible cases.

BTW, I'm using Yosemite 10.10.4 on MBP 15" Mid 2014.

0
TheCommoner282

Okay, this is not complete, but I ran out of time.

So, I use the df command, because I know that this will have the mount point at the end. Then I grep it with a pattern of slash newline. And then I wanted to cut everything after the first space sign out. But the cutting out doesn't work right now. Don't really know what I am doing wrong and I have to start working for my job right now, but maybe you can improve the cutting out of the bash feature. Sorry, no time to look the manual up to find my mistake. But we're almost there:

Corrected:

foo=$(df -h | grep -e ' /$'); loo=$; echo $loo 

Now it works. Try it :)

EDIT: Oh, I just realised that I am using a lvg, therefore disk0s[0-4] will be translated to disk1. So, test it and tell me if this is correctly showing you the right disk you're not using an lvg.

EDIT 2: Still not working for encrypted logic volume group, but if you could test this one without FileVault, it should work

foo=$(mount | grep -e ' / '); foo=$; diskutil list | grep "[0-99]:" | grep $ | grep EFI) 

This would look for an EFI on the disk on which ist mounted as root, so usually MacintoshHD

EDIT 3: This is really great to kill time at work. Okay, I guess this should give you the right answer. It can do so even if it is FileVault encrypted.

#!/bin/bash maindrive=$(mount | grep -e " / ") maindrive_exact=$ maindrive_reduced=$ if [ "$(diskutil list | grep Unlocked)" = "" ] then diskline=$(diskutil list | grep "[0-99]:" | grep $maindrive_reduced | grep EFI) diskline_cut1=$ diskline_cut2=$ echo "/dev/$diskline_cut2" else alldisk=$(diskutil list) alldisk_cut1=$} alldisk_cut2=$ alldisk_cut3=$ echo /dev/$alldisk_cut3 fi 

So, this should give you the EFI partition on the same hard drive as your root folder MacintoshHD.

EDIT 4 (Hopefully final version)

#!/bin/bash maindrive=$(mount | grep -e " / ") maindrive_exact=$ maindrive_reduced=$ function getdisknumber { diskline=$(diskutil list | grep "[0-99]:" | grep $maindrive_reduced | grep EFI) diskline_cut1=$ diskline_cut2=$ echo "/dev/$diskline_cut2" } if [ "$(diskutil list | grep Unlocked)" = "" ] then getdisknumber else alldisk=$(diskutil list) alldisk_cut=$} alldisk_cut=$ alldisk_cut=$ alldisk_cut=$ maindrive_reduced=$alldisk_cut getdisknumber fi 

And here's the explanation

Okay, as ask in the comment, the explanation what %%,%,##,# means. All those symbols cut out information of a string. %%pattern cuts out the biggest pattern matching part to the right. %pattern cuts out the smallest pattern matching part to the right. ##pattern cuts out the biggest pattern matching part to the left #pattern cuts out the smallest pattern matching part to the left 

The else part of the script now tries to find the right hard drive when confronted with a FileVault created encrypted Volume. The function then cuts this hard drive down to the disk information on this hard drive, looking for EFI as a keyword.

Here's a link about cutting strings in bash Cutting strings

EDIT 5: Alright. Another iteration of this script. Very, very down to the basics.

#!/bin/bash ## Find the main hard drive maindrive=$(mount | grep -e " / ") maindrive=$ maindrive=$ ## Checking for FileVault if [ "" != "$(diskutil list /dev/disk1 | grep "Unlocked Encrypted")" ] then maindrive=$(diskutil list | grep "Logical Volume on") maindrive=$ maindrive=$ fi ## Checking for EFI EFI_DRIVE=$(diskutil list /dev/$maindrive | grep EFI) EFI_DRIVE=$ echo "/dev/$EFI_DRIVE" 

Just to be complete, that's my diskutil list:

/dev/disk0 #: TYPE NAME SIZE IDENTIFIER 0: GUID_partition_scheme *250.1 GB disk0 1: EFI EFI 209.7 MB disk0s1 2: Apple_CoreStorage 249.2 GB disk0s2 3: Apple_Boot Recovery HD 650.0 MB disk0s3 /dev/disk1 #: TYPE NAME SIZE IDENTIFIER 0: Apple_HFS Macintosh HD *248.8 GB disk1 Logical Volume on disk0s2 xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx Unlocked Encrypted 

And this happens when I run the script:

Joes-MacBook-Pro:EFI_Script joe$ chmod +x EFI_Script Joes-MacBook-Pro:EFI_Script joe$ ./EFI_Script /dev/disk0s1 Joes-MacBook-Pro:EFI_Script joe$ 

I have thought about why it didn't work for you so far. So, basically, if that doesn't work either, I need two information from you. First, I will need to know your output for the ' mount ' command. Mine looks like this:

Joes-MacBook-Pro:EFI_Script joe$ mount /dev/disk1 on / (hfs, local, journaled) devfs on /dev (devfs, local, nobrowse) map -hosts on /net (autofs, nosuid, automounted, nobrowse) map auto_home on /home (autofs, automounted, nobrowse) 

As you see, it does give me the mountpoint '/' on 'disk1'. I simply assumed, if FileVault is turned off, it would give you your mountpoint on disk0. But maybe I am wrong and I have no system on which FileVault is turned off. So, should your mountpoint be also on disk1 while the EFI is on disk0, it should return empty or with only /dev/ since this is what I added manually. On the other hand, if I remember correctly, you had an EFI partition on disk1, too.

Anyway, the second thing I need would be that you run this script with the command 'bash -x script', so that it shows what it does while it is running. This way, we could see what goes wrong.

Anyway, I hope it just works and we don't have to go to these length. But if not, we have to figure out another way to find the main hard drive.

Anyway, test it. Cheers!

Ух ты, TheCommoner282, ты пошел в город на этом. `foo = $ (df -h | grep -e '/ $'); loo = $ ; echo $ loo` и `выдает неправильный идентификатор диска,` foo = $ (mount | grep -e '/'); foo = $ ; список рассылки | grep "[0-99]:" | grep $ | grep EFI; echo $ foo` производит / dev / disk0s2, а не / dev / disk0s1. Завтра я проверю твой длинный сценарий. Из интереса можете ли вы объяснить, что делает использование символов %% и ##, поскольку я не могу найти какую-либо документацию по ним в Интернете. Т.е. в $ ? Я стремлюсь учиться. juliushibert 8 лет назад 0
Я отредактирую объяснение в. Кроме того, я нашел ошибку в своем сценарии и исправлю ее TheCommoner282 8 лет назад 0
Боже мой, ты прав. Я просто посмотрел на вторую строку. Это просто свалка. Я 'echo $ foo', который не изменяется на втором этапе. И предыдущий «список дисков», вероятно, окажется пустым. Ну, плохое начало. Но будем надеяться, что четвертая итерация работает TheCommoner282 8 лет назад 0
Извините, что я потратил некоторое время, чтобы проверить ваше последнее предложение @ TheCommoner282 К сожалению, скрипт просто выводит `/ dev /`. Спасибо за объяснение по сокращению в BASH. Действительно хорошая информация, чтобы знать. juliushibert 8 лет назад 0
Как странно. Я предполагаю, что должна быть некоторая разница между нашими выводами Diskutil, которые я не учел. Я перепишу скрипт и попробую учесть. Также я постараюсь добавить использовать ваш вывод, который вы разместили в тестовых целях. У меня есть идея или два, как ограничить это меньшим количеством информации, что означает меньшее сокращение и, следовательно, меньше ошибок или возможностей. Вы можете ожидать эту новую версию до завтра. Я сделаю это сегодня вечером (по Европе, GMT + 1) TheCommoner282 8 лет назад 0
@juliushibert, я добавил еще одну версию. И я добавил несколько инструкций о том, как найти проблему, если она не будет работать снова. В любом случае, просто комментируя здесь, вы получите уведомление. Я надеюсь, что это работает сейчас. Приветствия. TheCommoner282 8 лет назад 0
0
madeddie

I'd assume /dev/disk0 is always the "main" HDD, right? If not and you really want to find the EFI partition on the disk named "Macintosh HD" then your oneliner is almost correct.

For me $6 returns 'GB' and I'm also assuming the EFI partition is always the first of that particular disk, so try:

diskutil list | grep 'Macintosh HD' | awk '' | sed 's/s[0-9]/s1/' 

or some more awk trickery (for good measure):

diskutil list | awk '/Macintosh HD/ { sub(/s[0-9]/, "s1", $(NF)); print $(NF) }'