Search code examples
linuxbashshelludev

Bash script doesn't wait until commands have been properly executed


I am working on a very simple script but for some reason parts of it seem to run asynchronously.

singlePartDevice() {
# http://www.linuxquestions.org/questions/linux-software-2/removing-all-partition-from-disk-690256/
# http://serverfault.com/questions/257356/mdadm-on-ubuntu-10-04-raid5-of-4-disks-one-disk-missing-after-reboot
# Create single partition
parted -s "$1" mklabel msdos
# Find size of disk
v_disk=$(parted -s "$1" print|awk '/^Disk/ {print $3}'|sed 's/[Mm][Bb]//')
parted -s "$1" mkpart primary ext3 4096 ${v_disk}
parted -s "$1" set 1 raid on
return 0
}

singlePartDevice "/dev/sdc"
singlePartDevice "/dev/sdd"

#/dev/sdc1 exists but /dev/sdd1 does not exist
sleep 5s
#/dev/sdc1 exists AND /dev/sdd1 does also exist

As you see before the call of sleep the script has only partially finished its job. How do I make my script to wait until parted has done its job sucessfully?


Solution

  • (I am assuming that you are working on Linux due to the links in your question)

    I am not very familiar with parted, but I believe that the partition device nodes are not created directly by it - they are created by udev, which is by nature an asynchronous procedure:

    • parted creates a partition
    • the kernel updates its internal state
    • the kernel notifies the udev daemon (udevd)
    • udevd checks its rule files (usually under /etc/udev/) and creates the appropriate device nodes

    This procedure allows for clear separation of the device node handling policy from the kernel, which is a Good Thing (TM). Unfortunately, it also introduces relatively unpredictable delays.

    A possible way to handle this is to have your script wait for the device nodes to appear:

    while [ ! -e "/dev/sdd1" ]; do sleep 1; done