How can I automatically format and write data to an SD card when it is plugged in? (Trigger systemd service...












0















I'd like to flash SD cards with a custom script (writes partition table, then copies over a rootfs, etc.) whenever an SD card is inserted.



At first glance this seemed straightforward -- I'd just use a udev rule to detect the SD card then call the script. The first problem is that since the reader already exists, it doesn't trigger an "add" just a "change", and not only that, it would cause multiple events and trigger the script multiple times. After some more filters I was able to get a simple script to trigger only once (/etc/udev/rules.d/99-sd-detect.rules):



ACTION=="change", KERNEL=="sd[b-z]", SUBSYSTEM=="block", ENV{DISK_MEDIA_CHANGE}=="1", ENV{DEVTYPE}=="disk", ATTRS{idVendor}=="8564", ATTRS{idProduct}=="4000", ENV{ID_DRIVE_FLASH_CF}=="1", RUN+="/bin/sh -c '/root/udev_flash_sd.sh %E{DEVNAME}'"


However, when I actually have the script write data to the SD card it is killed after a few seconds. Apparently in 2012 udev made changes that kill processes that don't return after a few seconds. I tried various forking/detaching/nohup etc. trying to keep it running, but to no avail.



It seems the proper solution is to have it call a systemd service to run anything that takes longer, e.g., something like:



ACTION=="change", KERNEL=="sd[b-z]", SUBSYSTEM=="block", ENV{DISK_MEDIA_CHANGE}=="1", ENV{DEVTYPE}=="disk", ATTRS{idVendor}=="8564", ATTRS{idProduct}=="4000", ENV{ID_DRIVE_FLASH_CF}=="1", TAG+="systemd", PROGRAM="/bin/systemd-escape -p --template=flash_sd@.service $env{DEVNAME}", ENV{SYSTEMD_WANTS}+="%c"


Where /etc/systemd/system/flash_sd@.service has:



[Unit]
BindTo=%i.device
After=%i.device

[Service]
Type=oneshot
TimeoutStartSec=360
ExecStart=/root/udev_flash_sd.sh /%I


This works if you call "systemctl start flash_sd@dev-sde.service", which is also what the PROGRAM part of the udev rule outputs (at least for /dev/sde). After much searching it looks like udev will not call the service on a "change" event, only an "add". ("udevadm monitor -p" shows the SYSTEMD_WANTS and tag correctly, not to mention testing a simple add rule that calls a systemd service works fine.)



So, how do I call a custom flashing script automatically upon insertion of an SD card?










share|improve this question



























    0















    I'd like to flash SD cards with a custom script (writes partition table, then copies over a rootfs, etc.) whenever an SD card is inserted.



    At first glance this seemed straightforward -- I'd just use a udev rule to detect the SD card then call the script. The first problem is that since the reader already exists, it doesn't trigger an "add" just a "change", and not only that, it would cause multiple events and trigger the script multiple times. After some more filters I was able to get a simple script to trigger only once (/etc/udev/rules.d/99-sd-detect.rules):



    ACTION=="change", KERNEL=="sd[b-z]", SUBSYSTEM=="block", ENV{DISK_MEDIA_CHANGE}=="1", ENV{DEVTYPE}=="disk", ATTRS{idVendor}=="8564", ATTRS{idProduct}=="4000", ENV{ID_DRIVE_FLASH_CF}=="1", RUN+="/bin/sh -c '/root/udev_flash_sd.sh %E{DEVNAME}'"


    However, when I actually have the script write data to the SD card it is killed after a few seconds. Apparently in 2012 udev made changes that kill processes that don't return after a few seconds. I tried various forking/detaching/nohup etc. trying to keep it running, but to no avail.



    It seems the proper solution is to have it call a systemd service to run anything that takes longer, e.g., something like:



    ACTION=="change", KERNEL=="sd[b-z]", SUBSYSTEM=="block", ENV{DISK_MEDIA_CHANGE}=="1", ENV{DEVTYPE}=="disk", ATTRS{idVendor}=="8564", ATTRS{idProduct}=="4000", ENV{ID_DRIVE_FLASH_CF}=="1", TAG+="systemd", PROGRAM="/bin/systemd-escape -p --template=flash_sd@.service $env{DEVNAME}", ENV{SYSTEMD_WANTS}+="%c"


    Where /etc/systemd/system/flash_sd@.service has:



    [Unit]
    BindTo=%i.device
    After=%i.device

    [Service]
    Type=oneshot
    TimeoutStartSec=360
    ExecStart=/root/udev_flash_sd.sh /%I


    This works if you call "systemctl start flash_sd@dev-sde.service", which is also what the PROGRAM part of the udev rule outputs (at least for /dev/sde). After much searching it looks like udev will not call the service on a "change" event, only an "add". ("udevadm monitor -p" shows the SYSTEMD_WANTS and tag correctly, not to mention testing a simple add rule that calls a systemd service works fine.)



    So, how do I call a custom flashing script automatically upon insertion of an SD card?










    share|improve this question

























      0












      0








      0








      I'd like to flash SD cards with a custom script (writes partition table, then copies over a rootfs, etc.) whenever an SD card is inserted.



      At first glance this seemed straightforward -- I'd just use a udev rule to detect the SD card then call the script. The first problem is that since the reader already exists, it doesn't trigger an "add" just a "change", and not only that, it would cause multiple events and trigger the script multiple times. After some more filters I was able to get a simple script to trigger only once (/etc/udev/rules.d/99-sd-detect.rules):



      ACTION=="change", KERNEL=="sd[b-z]", SUBSYSTEM=="block", ENV{DISK_MEDIA_CHANGE}=="1", ENV{DEVTYPE}=="disk", ATTRS{idVendor}=="8564", ATTRS{idProduct}=="4000", ENV{ID_DRIVE_FLASH_CF}=="1", RUN+="/bin/sh -c '/root/udev_flash_sd.sh %E{DEVNAME}'"


      However, when I actually have the script write data to the SD card it is killed after a few seconds. Apparently in 2012 udev made changes that kill processes that don't return after a few seconds. I tried various forking/detaching/nohup etc. trying to keep it running, but to no avail.



      It seems the proper solution is to have it call a systemd service to run anything that takes longer, e.g., something like:



      ACTION=="change", KERNEL=="sd[b-z]", SUBSYSTEM=="block", ENV{DISK_MEDIA_CHANGE}=="1", ENV{DEVTYPE}=="disk", ATTRS{idVendor}=="8564", ATTRS{idProduct}=="4000", ENV{ID_DRIVE_FLASH_CF}=="1", TAG+="systemd", PROGRAM="/bin/systemd-escape -p --template=flash_sd@.service $env{DEVNAME}", ENV{SYSTEMD_WANTS}+="%c"


      Where /etc/systemd/system/flash_sd@.service has:



      [Unit]
      BindTo=%i.device
      After=%i.device

      [Service]
      Type=oneshot
      TimeoutStartSec=360
      ExecStart=/root/udev_flash_sd.sh /%I


      This works if you call "systemctl start flash_sd@dev-sde.service", which is also what the PROGRAM part of the udev rule outputs (at least for /dev/sde). After much searching it looks like udev will not call the service on a "change" event, only an "add". ("udevadm monitor -p" shows the SYSTEMD_WANTS and tag correctly, not to mention testing a simple add rule that calls a systemd service works fine.)



      So, how do I call a custom flashing script automatically upon insertion of an SD card?










      share|improve this question














      I'd like to flash SD cards with a custom script (writes partition table, then copies over a rootfs, etc.) whenever an SD card is inserted.



      At first glance this seemed straightforward -- I'd just use a udev rule to detect the SD card then call the script. The first problem is that since the reader already exists, it doesn't trigger an "add" just a "change", and not only that, it would cause multiple events and trigger the script multiple times. After some more filters I was able to get a simple script to trigger only once (/etc/udev/rules.d/99-sd-detect.rules):



      ACTION=="change", KERNEL=="sd[b-z]", SUBSYSTEM=="block", ENV{DISK_MEDIA_CHANGE}=="1", ENV{DEVTYPE}=="disk", ATTRS{idVendor}=="8564", ATTRS{idProduct}=="4000", ENV{ID_DRIVE_FLASH_CF}=="1", RUN+="/bin/sh -c '/root/udev_flash_sd.sh %E{DEVNAME}'"


      However, when I actually have the script write data to the SD card it is killed after a few seconds. Apparently in 2012 udev made changes that kill processes that don't return after a few seconds. I tried various forking/detaching/nohup etc. trying to keep it running, but to no avail.



      It seems the proper solution is to have it call a systemd service to run anything that takes longer, e.g., something like:



      ACTION=="change", KERNEL=="sd[b-z]", SUBSYSTEM=="block", ENV{DISK_MEDIA_CHANGE}=="1", ENV{DEVTYPE}=="disk", ATTRS{idVendor}=="8564", ATTRS{idProduct}=="4000", ENV{ID_DRIVE_FLASH_CF}=="1", TAG+="systemd", PROGRAM="/bin/systemd-escape -p --template=flash_sd@.service $env{DEVNAME}", ENV{SYSTEMD_WANTS}+="%c"


      Where /etc/systemd/system/flash_sd@.service has:



      [Unit]
      BindTo=%i.device
      After=%i.device

      [Service]
      Type=oneshot
      TimeoutStartSec=360
      ExecStart=/root/udev_flash_sd.sh /%I


      This works if you call "systemctl start flash_sd@dev-sde.service", which is also what the PROGRAM part of the udev rule outputs (at least for /dev/sde). After much searching it looks like udev will not call the service on a "change" event, only an "add". ("udevadm monitor -p" shows the SYSTEMD_WANTS and tag correctly, not to mention testing a simple add rule that calls a systemd service works fine.)



      So, how do I call a custom flashing script automatically upon insertion of an SD card?







      systemd udev






      share|improve this question













      share|improve this question











      share|improve this question




      share|improve this question










      asked Jan 26 at 8:32









      cwshepcwshep

      14




      14






















          1 Answer
          1






          active

          oldest

          votes


















          0














          Edit: It seems the best method is to pipe your command to "at now" to keep udev from killing it. E.g., "echo mycommand.sh | at now".



          Originally it seemed that "& disown" would work, but it actually encounters the same problem as udev killing it, just after 300s (5m) rather than ~2-3s.






          share|improve this answer


























            Your Answer








            StackExchange.ready(function() {
            var channelOptions = {
            tags: "".split(" "),
            id: "3"
            };
            initTagRenderer("".split(" "), "".split(" "), channelOptions);

            StackExchange.using("externalEditor", function() {
            // Have to fire editor after snippets, if snippets enabled
            if (StackExchange.settings.snippets.snippetsEnabled) {
            StackExchange.using("snippets", function() {
            createEditor();
            });
            }
            else {
            createEditor();
            }
            });

            function createEditor() {
            StackExchange.prepareEditor({
            heartbeatType: 'answer',
            autoActivateHeartbeat: false,
            convertImagesToLinks: true,
            noModals: true,
            showLowRepImageUploadWarning: true,
            reputationToPostImages: 10,
            bindNavPrevention: true,
            postfix: "",
            imageUploader: {
            brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
            contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
            allowUrls: true
            },
            onDemand: true,
            discardSelector: ".discard-answer"
            ,immediatelyShowMarkdownHelp:true
            });


            }
            });














            draft saved

            draft discarded


















            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fsuperuser.com%2fquestions%2f1398666%2fhow-can-i-automatically-format-and-write-data-to-an-sd-card-when-it-is-plugged-i%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown

























            1 Answer
            1






            active

            oldest

            votes








            1 Answer
            1






            active

            oldest

            votes









            active

            oldest

            votes






            active

            oldest

            votes









            0














            Edit: It seems the best method is to pipe your command to "at now" to keep udev from killing it. E.g., "echo mycommand.sh | at now".



            Originally it seemed that "& disown" would work, but it actually encounters the same problem as udev killing it, just after 300s (5m) rather than ~2-3s.






            share|improve this answer






























              0














              Edit: It seems the best method is to pipe your command to "at now" to keep udev from killing it. E.g., "echo mycommand.sh | at now".



              Originally it seemed that "& disown" would work, but it actually encounters the same problem as udev killing it, just after 300s (5m) rather than ~2-3s.






              share|improve this answer




























                0












                0








                0







                Edit: It seems the best method is to pipe your command to "at now" to keep udev from killing it. E.g., "echo mycommand.sh | at now".



                Originally it seemed that "& disown" would work, but it actually encounters the same problem as udev killing it, just after 300s (5m) rather than ~2-3s.






                share|improve this answer















                Edit: It seems the best method is to pipe your command to "at now" to keep udev from killing it. E.g., "echo mycommand.sh | at now".



                Originally it seemed that "& disown" would work, but it actually encounters the same problem as udev killing it, just after 300s (5m) rather than ~2-3s.







                share|improve this answer














                share|improve this answer



                share|improve this answer








                edited Jan 27 at 7:04

























                answered Jan 27 at 2:22









                cwshepcwshep

                14




                14






























                    draft saved

                    draft discarded




















































                    Thanks for contributing an answer to Super User!


                    • Please be sure to answer the question. Provide details and share your research!

                    But avoid



                    • Asking for help, clarification, or responding to other answers.

                    • Making statements based on opinion; back them up with references or personal experience.


                    To learn more, see our tips on writing great answers.




                    draft saved


                    draft discarded














                    StackExchange.ready(
                    function () {
                    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fsuperuser.com%2fquestions%2f1398666%2fhow-can-i-automatically-format-and-write-data-to-an-sd-card-when-it-is-plugged-i%23new-answer', 'question_page');
                    }
                    );

                    Post as a guest















                    Required, but never shown





















































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown

































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown







                    Popular posts from this blog

                    "Incorrect syntax near the keyword 'ON'. (on update cascade, on delete cascade,)

                    Alcedinidae

                    RAC Tourist Trophy