Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
421 views
in Technique[技术] by (71.8m points)

bash - Why does Rsync of tree structure into root break filesystem on Raspberry Pi?

I have developed an application which I am trying to install on raspberry pi via a script. The directory structure I have is this:

pi@raspberrypi:~/inetdrm $ tree files.rpi/

files.rpi/
├── etc
│?? └── config
│??     └── inetdrm
├── lib
│?? └── systemd
│??     └── system
│??         └── inetdrm.service
└── usr
    └── local
        └── bin
            └── inetdrm

When I try to install the tree structure onto the pi with this install.sh: script

#! /bin/bash
FILES="./files.rpi"
sudo rsync -rlpt "$FILES/" /
sudo chmod 644 /lib/systemd/system/inetdrm.service
sudo chmod +x /usr/local/bin/inetdrm
#sudo systemctl start inetdrm.service
#sudo systemctl enable inetdrm.service

The filesystem on the pi breaks. I loose all access to commands, the script fails, as shown on this transcript.

pi@raspberrypi:~/inetdrm $ ./install.sh 
./install.sh: line 4: /usr/bin/sudo: No such file or directory
./install.sh: line 5: /usr/bin/sudo: No such file or directory
pi@raspberrypi:~/inetdrm $ ls
-bash: /usr/bin/ls: No such file or directory
pi@raspberrypi:~/inetdrm $ pwd
/home/pi/inetdrm
pi@raspberrypi:~/inetdrm $ ls /
-bash: /usr/bin/ls: No such file or directory
pi@raspberrypi:~/inetdrm $ 

Rebooting the pi results in kernel panic due to no init. Does anyone know what's going on?


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

Ok, so after a good nights sleep, I worked out what is going on.

Rsync doesn't just do a simple copy or replace operation. It first makes a temporary copy of what it is replacing, and then moves that temporary copy into place. When doing a folder merge, it seems it does something similar causing (in my case) all the binaries in the /usr/* tree to be replaced while some are still in use.

The solution: use --inplace ie:

sudo rsync --inplace -rlpt "$FILES/" /

which causes rsync to work on the files (and directories, it seems) in their existing location rather than doing a copy-and-move.

I have tested the solution and confirmed it works, but I can not find any explicit mention of how rsync handles directory merge without the --inplace flag, so if someone can provide more info, that'd be great.

UPDATE: I found that when using --inplace the issue still occurs if rsync is interrupted for some reason. I'm not entirely certain about the inner workings of directory merge in rsync, so I have concluded that it may not be the best tool for this job. Instead I wrote my own deployment function. Here it is in case anyone stumbling across this post finds it useful:

#! /bin/bash
FILES="files.rpi"

installFiles(){
  FILELIST=$(find "$1" -type f)
  for SRC in $FILELIST; do
    DEST="/$(echo "$SRC"| cut -f 2- -d/)"
    DIR=$(dirname "$DEST")
    if [ ! -d "$DIR" ]; then
      sudo mkdir -p "$DIR"
    fi
    echo "$SRC => $DEST"
    sudo cp "$SRC" "$DEST"
  done
}

installFiles "$FILES"

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...