QProcess on MacOS has some issues
-
Qt 5.12
I am trying to get the volume ID on macOS and using the following function:
QString getVolumeInfo() { QString volumeID = "Cannot find the volumeID"; QProcess p; //diskutil info $(df -h / | tail -1 | cut -d' ' -f 1) QString command = "diskutil"; QStringList args; args << "info" << "$(df -h / | tail -1 | cut -d' ' -f 1)"; p.start(command, args); p.waitForStarted(); p.waitForFinished(); foreach(QString line, QString(p.readAll()).split("\n")) { if(line.contains("Volume UUID:")) volumeID = line; } return volumeID; }
I have to use the diskutil because of the limitation with macOS. However, QProcess, reading the object has nothing in it.
Command on terminal: diskutil info $(df -h / | tail -1 | cut -d' ' -f 1)
which returns a ton of information like:
...
SMART Status: Verified
Volume UUID: 954BACF1-EBC5-4D14-86FB-0912CF7F839C
Disk / Partition UUID: 954BACF1-EBC5-4D14-86FB-0912CF7F839CDisk Size: 500.1 GB (500068036608 Bytes) (exactly 976695384 512-Byte-Units)
....
When I try to add qDebug() to debug I get the following: true - "Could not find disk: $(df -h / | tail -1 | cut -d' ' -f 1)\n"
So seem like the arguments is not formatted or something?
I am trying to implement: https://apple.stackexchange.com/questions/50302/how-can-i-tell-which-volume-the-operating-system-is-on
-
Hi,
To do such chaining you should use QProcess::setStandardOutputProcess and create as many QProcess as command you have.
However, you can avoid using cut and simply use QString parsing on the output of tail -1 or may just par the output of df in your application and then call
diskutil
on the result. -
You will need to explicitly run a shell if you want to have the $() be evaluated by a shell. When you run a command like that on the command line, the shell spawns four separate processes. One process for df, one process for tail, one process for cut. And the finally when the result of the $() is fully evaluated, it runs a process for diskutil, with the result of the $() block. The shell doesn't try to pass the whole raw command line to exec to try and have the kernel sort it out -- it has to do that itself. If you don't want to handle it yourself, you need to run something like sh -c 'diskutil info $(foo)'
-
You will need to explicitly run a shell if you want to have the $() be evaluated by a shell. When you run a command like that on the command line, the shell spawns four separate processes. One process for df, one process for tail, one process for cut. And the finally when the result of the $() is fully evaluated, it runs a process for diskutil, with the result of the $() block. The shell doesn't try to pass the whole raw command line to exec to try and have the kernel sort it out -- it has to do that itself. If you don't want to handle it yourself, you need to run something like sh -c 'diskutil info $(foo)'
you need to run something like
sh -c 'diskutil info $(foo)'
That's how I would do if I were the OP and I didn't want to start creating separate processes for each segment (though as @SGaist observed you could probably do this one yourself by skipping
tail
&cut
and parsing yourself).However, though I haven't tested, I would have thought that
sh
, Bourne shell, was not up to the job of$(...)
and you'd want something more like/bin/bash -c
? -
Thank you all. I have managed to sort it out after understanding from the comments above. Thank you all.
I still have to try and cull a few commands off the args but currently, it works and I quite understand the whole situation.
QStringList args; args << "-c" << "diskutil info $(df -h / | tail -1 | cut -d' ' -f 1)"; p.start("/bin/bash", args);
-
you need to run something like
sh -c 'diskutil info $(foo)'
That's how I would do if I were the OP and I didn't want to start creating separate processes for each segment (though as @SGaist observed you could probably do this one yourself by skipping
tail
&cut
and parsing yourself).However, though I haven't tested, I would have thought that
sh
, Bourne shell, was not up to the job of$(...)
and you'd want something more like/bin/bash -c
?@JonB Yeah, you should probably be explicit about which shell you want. On OS-X 'sh' is apparently bash anyway so it lets me get away with it. It's definitely not a portable assumption though, and could lead to a lot of "It works on my machine" kind of problems.
/shrug
wills-mbp:list $uname -a Darwin wills-mbp 18.2.0 Darwin Kernel Version 18.2.0: Mon Nov 12 20:24:46 PST 2018; root:xnu-4903.231.4~2/RELEASE_X86_64 x86_64 wills-mbp:list $sh -c 'echo $(echo 123)' 123 wills-mbp:list $sh --version GNU bash, version 3.2.57(1)-release (x86_64-apple-darwin18) Copyright (C) 2007 Free Software Foundation, Inc.
-
@JonB Yeah, you should probably be explicit about which shell you want. On OS-X 'sh' is apparently bash anyway so it lets me get away with it. It's definitely not a portable assumption though, and could lead to a lot of "It works on my machine" kind of problems.
/shrug
wills-mbp:list $uname -a Darwin wills-mbp 18.2.0 Darwin Kernel Version 18.2.0: Mon Nov 12 20:24:46 PST 2018; root:xnu-4903.231.4~2/RELEASE_X86_64 x86_64 wills-mbp:list $sh -c 'echo $(echo 123)' 123 wills-mbp:list $sh --version GNU bash, version 3.2.57(1)-release (x86_64-apple-darwin18) Copyright (C) 2007 Free Software Foundation, Inc.
@wrosecrans
Wow, I wouldn't have known that (only ever having used a Mac just after they were invented)! Under my Ubuntu:jon@ubuntu:~$ sh --version sh: 0: Illegal option -- jon@ubuntu:~$
That's more to my liking :) Having said that, it appears
sh -c 'echo $(echo 123)'
does work, though I'm sure it didn't in the 80s! Personally, I'd still rather use backticks...Incidentally, in your command prompt I note you have no space after the
$
. I thought you were typing$sh
etc. Don't you/Mac want one? :) -
@wrosecrans
Wow, I wouldn't have known that (only ever having used a Mac just after they were invented)! Under my Ubuntu:jon@ubuntu:~$ sh --version sh: 0: Illegal option -- jon@ubuntu:~$
That's more to my liking :) Having said that, it appears
sh -c 'echo $(echo 123)'
does work, though I'm sure it didn't in the 80s! Personally, I'd still rather use backticks...Incidentally, in your command prompt I note you have no space after the
$
. I thought you were typing$sh
etc. Don't you/Mac want one? :)@JonB If you wanna really annoy your brain with trivia about bash/sh on OS-X, they are both bash, but they are separate copies of slightly different bash binaries that were built separately, rather than a symlink from one to the other or something:
$ ls -lh /bin/bash /bin/sh -r-xr-xr-x 1 root wheel 604K Nov 29 21:55 /bin/bash -r-xr-xr-x 1 root wheel 604K Nov 29 21:55 /bin/sh $ md5 /bin/bash /bin/sh MD5 (/bin/bash) = b513c6e7c86e43eb93f4fd56e28bd540 MD5 (/bin/sh) = be55e8952a262d0e524239dbf82191ed
I have no idea why, but presumably it is possible to get some sort of different behavior between the two shells as a result of them being almost, but not quite, the same thing.
I never really noticed my lack of space, but I can see how it would be confusing out of context, ha ha. I have been fiddling with my PS1 prompt recently, so I probably screwed it up then. I now have the output of pwd going the the whizzy (and otherwise mostly useless) touchbar on my MacBook Pro as a part of generating the prompt, so the prompt in the terminal can be quite terse and not take up much space.