How can I automatically format and write data to an SD card when it is plugged in? (Trigger systemd service...
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
add a comment |
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
add a comment |
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
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
systemd udev
asked Jan 26 at 8:32
cwshepcwshep
14
14
add a comment |
add a comment |
1 Answer
1
active
oldest
votes
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.
add a comment |
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
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
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.
add a comment |
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.
add a comment |
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.
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.
edited Jan 27 at 7:04
answered Jan 27 at 2:22
cwshepcwshep
14
14
add a comment |
add a comment |
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.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
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