Como esperar que o processo de cópia (cp) termine?

5

Eu quero meu RPi 2 (com MiniBian (uma versão mínima do sistema operacional Raspbian baseado em Debian) como seu sistema operacional) para executar um script quando ele detectar que uma memória flash USB está inserida. Então é isso que eu fiz:

Eu criei /etc/udev/rules.d/10-usbstick.rules com estes conteúdos:

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

Em seguida, crie /path/to/myscript.sh com estes conteúdos:

#!/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

Agora, quando insiro uma memória flash USB, ela reconhece, monta, para o daemon omxd e remove todos os arquivos mais antigos.

Mas o problema é que ele é desligado ( halt ) antes de todos os arquivos terem sido copiados. Eu verifico mais tarde e vejo que apenas 1 arquivo foi copiado e não foi copiado corretamente, como o comando halt foi executado no meio do procedimento de cópia.

Então, decidi usar o comando wait para garantir que o comando halt fosse executado apenas no final. Eu editei o arquivo /path/to/myscript.sh como este:

#!/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

Mas novamente o mesmo cenário acontece: o sistema pára no meio do procedimento de cópia.

Então, o que há de errado com o meu sistema?

O que devo fazer para dizer ao sistema para halt somente após todos os novos arquivos terem sido copiados com sucesso!?

Atualização 1

A adição de sync antes de umount e halt não funcionou. O mesmo cenário acontece novamente.

Atualização 2

Eu editei o arquivo /path/to/myscript.sh da seguinte forma:

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

Mas também não ajudou! O mesmo cenário acontece novamente! E desta vez foi pior: não copiou nenhum arquivo!

Atualização 3

Alterei o /etc/udev/rules.d/10-usbstick.rules para o seguinte:

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

Agora funciona muito bem. Copia todos os arquivos. Mas há um novo problema: ele não desliga!

Atualização 4

Eu encontrei algo novo:

Quando eu executo myscript.sh diretamente do terminal, ele funciona perfeitamente: remove os arquivos mais antigos, copia os novos arquivos e desliga o sistema. Perfeito.

Então, por que ele não executa myscript.sh perfeitamente quando eu o chamo das regras do udev?

E existe alguma outra maneira de desligar o sistema depois que ele copiou os arquivos!?

    
por Omid1989 14.01.2016 / 14:33

2 respostas

2

Eu não sei por que mudar o nome do kernel teria feito a diferença (talvez sd*1 seja executado após sd* , permitindo um pouco mais de tempo para o trabalho ser feito?), mas o udev não gosta de execução longa ações em eventos:

Starting daemons or other long running processes is not appropriate for udev; the forked processes, detached or not, will be unconditionally killed after the event handling has finished.

Original nohup sugestão

Eu originalmente sugeri nohup antes de ler meus próprios links :) - o que sugere que isso pode não funcionar de fato

regra do udev:

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

mywrapper.sh (Nota: se você não redirecionar a saída, o nohup pode esvaziar seu diretório com um arquivo nohup.out ):

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

Então myscript.sh pode ser o que é.

Mais recente systemd sugestão

O terceiro link abaixo sugere disparar um serviço systemd quando o dispositivo está conectado. Essa entrada no blog faz mais trabalho do que eu acho que você precisa, devido a garantir que as informações do dispositivo sejam passadas para o serviço, / em> você pode se safar simplesmente usando o systemd como seu método de daemonização:

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

Com um serviço simples, my-usb-backup.service :

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

Veja também:

por 16.01.2016 / 18:21
6

Não há nenhum ponto em um wait para um comando, a menos que seja executado em segundo plano (o que não é seu). O que você pode estar perdendo é um sync para forçar todas as gravações na mídia, embora isso deva acontecer como parte do comando umount .

Eu estaria interessado em ver se esse script simplificado funciona como você deseja:

#!/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

Devo admitir que estou um pouco confuso, já que sua descrição parece sugerir que você deseja atualizar arquivos no pendrive. Mas o seu código atualiza os arquivos em /path/to/my/folder do stick USB em vez de gravar em /mnt/usb/...

    
por 14.01.2016 / 14:39