복사 프로세스(cp)가 완료될 때까지 기다리는 방법은 무엇입니까?

복사 프로세스(cp)가 완료될 때까지 기다리는 방법은 무엇입니까?

USB 플래시 드라이브가 삽입되는 것을 감지하면 RPi 2( MiniBian최소 버전의 Debian 기반 OS 사용)를 운영 체제로 사용하여 스크립트를 실행하길 원합니다. Raspbian이것이 내가 한 일입니다:

저는 /etc/udev/rules.d/10-usbstick.rules다음 내용으로 이것을 만들었습니다:

ACTION=="add", SUBSYSTEM=="block", KERNEL=="sd*" SYMLINK+="usbflash", RUN+="/path/to/myscript.sh"

그런 다음 /path/to/myscript.sh다음 내용으로 만듭니다.

#!/bin/bash

mount /dev/usbflash /mnt/

service omxd stop

rm -r /path/to/myfolder/*
cp -f /mnt/*.mp4 /path/to/myfolder/
cp -f /mnt/*.avi /path/to/myfolder/

sleep 1
umount /dev/usbflash

halt

이제 USB 플래시 드라이브를 삽입하면 이를 인식하고 마운트한 다음 omxd데몬을 중지하고 모든 이전 파일을 삭제합니다.

그런데 문제는 halt모든 파일을 복사하기 전에 종료된다는 점입니다( ). 나중에 확인해 보니 파일이 1개만 복사되었는데, halt복사 과정에서 명령어를 실행한 것처럼 제대로 복사되지 않은 것이었습니다.

따라서 명령이 마지막에만 실행되도록 wait하기 위해 명령을 사용하기로 결정했습니다. 파일을 다음과 같이 편집했습니다 halt./path/to/myscript.sh

#!/bin/bash

mount /dev/usbflash /mnt/

PID1 = $!
wait PID1

service omxd stop

rm -r /path/to/myfolder/*

PID2 = $!
wait PID2

cp -f /mnt/*.mp4 /path/to/myfolder/

PID3 = $!
wait PID3

cp -f /mnt/*.avi /path/to/myfolder/

PID4 = $!
wait PID4

sleep 1
umount /dev/usbflash

PID5 = $!
wait PID5

halt

그러나 같은 일이 다시 발생했습니다. 복사 프로세스 중에 시스템이 중지되었습니다.

그럼 내 시스템에 무슨 문제가 있는 걸까요?

시스템에 알리려면 어떻게 해야 하나요?halt 그 후에야모든 새 파일이 성공적으로 복사되었습니다! ?


업데이트 1

sync이전에 추가했지만 umount효과 halt가 없습니다. 같은 장면이 또 일어났습니다.

업데이트 2

/path/to/myscript.sh파일을 다음과 같이 편집했습니다 .

mkdir -p /mnt/usb
if mount /dev/usbflash /mnt/usb
then
    service omxd stop
    rm -r /path/to/myfolder/*
    cp -f /mnt/usb/*.mp4 /path/to/myfolder/
    cp -f /mnt/usb/*.avi /path/to/myfolder/
    sync
    umount /mnt/usb
    sync
    shutdown -h now
fi

하지만 그것도 도움이 되지 않습니다! 같은 장면이 또 나왔네요! 이번에는 훨씬 더 나쁩니다. 파일을 전혀 복사하지 않습니다!

업데이트 3

나는 그것을 /etc/udev/rules.d/10-usbstick.rules다음과 같이 변경했습니다 :

ACTION=="add", SUBSYSTEM=="block", KERNEL=="sd[a-z]1" SYMLINK+="usbflash", RUN+="/path/to/myscript.sh"

지금은 잘 작동합니다. 모든 파일을 복사합니다. 하지만 새로운 문제가 있습니다. 끌 수 없습니다!

업데이트 4

나는 새로운 것을 발견했습니다:

터미널에서 직접 실행 myscript.sh하면 잘 작동합니다 . 이전 파일을 삭제하고 새 파일을 복사한 다음 시스템을 종료합니다. 완벽한.

myscript.sh그렇다면 udev 규칙에서 호출하면 왜 완벽하게 실행되지 않습니까?

파일 복사 후 시스템을 종료하는 다른 방법이 있나요? ?

답변1

waitfor 명령은 백그라운드에서 실행되지 않는 한 의미가 없습니다. 아마도 누락된 것은 sync모든 쓰기를 미디어에 강제로 적용하는 것입니다. 그러나 이는 umount명령의 일부로 발생해야 합니다.

이 단순화된 스크립트가 원하는 대로 작동하는지 확인하고 싶습니다.

#!/bin/bash
#
export PATH=/usr/local/bin:/bin:/usr/bin:/sbin:/usr/sbin

mkdir -p /mnt/usb
if mount /dev/usbflash /mnt/usb
then
    service omxd stop
    rm -r /path/to/myfolder/*
    cp -f /mnt/usb/*.mp4 /path/to/myfolder/
    cp -f /mnt/usb/*.avi /path/to/myfolder/
    sync
    umount /mnt/usb
    sync
    shutdown -h now
fi

귀하의 설명이 USB 스틱의 파일을 업데이트하고 싶다는 내용을 나타내는 것 같아서 약간 혼란스럽다는 점을 인정해야 합니다. 하지만 코드가 파일을 업데이트합니다./path/to/my/folder ~에서쓰기 대신 USB 스틱/mnt/usb/...

답변2

커널 이름을 변경하면 왜 영향을 미치는지 모르겠지만(아마도 sd*1작업을 완료하는 데 더 많은 시간을 허용한 후 실행됩니까?) udev는 이벤트에서 장기 실행 작업을 좋아하지 않습니다.sd*

데몬이나 기타 장기 실행 프로세스를 시작하는 것은 udev에 적합하지 않습니다. 분리 여부에 관계없이 분기된 프로세스는 이벤트 처리가 완료된 후 무조건 종료됩니다.

원래 nohup제안

나는 처음에 nohup내 링크를 완전히 읽기 전에 제안했습니다. :) - 이는 실제로 작동하지 않을 수도 있음을 나타냅니다.

udev 규칙:

ACTION=="add", SUBSYSTEM=="block", KERNEL=="sd[a-z]1" SYMLINK+="usbflash", RUN+="/path/to/mywrapper.sh"

mywrapper.sh(참고: 출력을 리디렉션하지 않으면 nohup이 디렉터리에 파일을 분산시킬 수 있습니다 nohup.out):

#!/bin/sh
nohup /path/to/myscript.sh >/log/myscript.log 2>&1 &

그렇다면 myscript.sh괜찮습니다.

최신 systemd제안

아래 세 번째 링크는 장치가 연결되면 systemd 서비스를 끄는 것을 제안합니다. 이 블로그 항목은 장치 정보가 서비스에 전달되는지 확인하는 데 필요하다고 생각하는 것보다 더 많은 작업을 수행하므로생각하다간단하게 systemd를 데몬 메서드로 사용할 수 있습니다.

ACTION=="add", SUBSYSTEM=="block", KERNEL=="sd[a-z]1" SYMLINK+="usbflash", RUN+="/usr/bin/systemctl start my-usb-backup.service"

간단한 일회성 서비스로 my-usb-backup.service:

[Unit]
Description=run myscript
[Service]
Type=oneshot
ExecStart=/path/to/myscript.sh

또한보십시오:

관련 정보