为什么树莓派上的树结构到根的Rsync会破坏文件系统



我开发了一个应用程序,我正试图通过脚本将其安装在树莓派上。我的目录结构是这样的:

pi@raspberrypi:~/inetdrm $ tree files.rpi/
files.rpi/
├── etc
│   └── config
│       └── inetdrm
├── lib
│   └── systemd
│       └── system
│           └── inetdrm.service
└── usr
└── local
└── bin
└── inetdrm

当我尝试用install.sh:脚本将树结构安装到pi上时

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

pi上的文件系统中断。我失去了对命令的所有访问权限,脚本失败了,如本文所示。

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 $ 

由于没有初始化,重新启动pi会导致内核死机。有人知道发生了什么事吗?

我遇到了同样的问题。事实证明Rsync不是适合这份工作的工具。我的解决方案是使用下面的脚本进行部署。在将文件写入目标目标之前,它会检查文件内容是否不同。因此,如果文件已经存在,它不会覆盖。你甚至可以在每次重新启动时自动运行它。

#!/usr/bin/env bash
FILES="files.rpi"
deploy_dir () {
shopt -s nullglob dotglob
for SRC in "${1}"/*; do
# Strip files dir prefix to get destination path
DST="${SRC#$FILES}"
if [ -d "${SRC}" ]; then
if [ -d "${DST}" ]; then
# Destination directory already exists,
# go one level deeper
deploy_dir "${SRC}"
else
# Destination directory doesn't exist,
# copy SRC dir (including contents) to DST
echo "${SRC} => ${DST}"
cp -r "${SRC}" "${DST}"
fi
else
# Only copy if contents aren't the same
# File attributes (owner, execution bit etc.) aren't considered by cmp!
# So if they change somehow, this deploy script won't correct them
cmp --silent "${SRC}" "${DST}" || echo "${SRC} => ${DST}" && cp "${SRC}" "${DST}"
fi
done
}
deploy_dir "${FILES}"

好的,所以在睡了一个好觉之后,我弄清楚了发生了什么。

Rsync不仅仅是一个简单的复制或替换操作。它首先对要替换的内容制作一个临时副本,然后将该临时副本移动到位。在进行文件夹合并时,它似乎做了类似的事情,导致(在我的情况下(/usr/*树中的所有二进制文件都被替换,而其中一些仍在使用中。

解决方案:使用--inplace即:

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

这导致rsync处理现有位置的文件(和目录(,而不是进行复制和移动。

我已经测试了这个解决方案并确认它有效,但我找不到任何明确提到rsync如何在没有--inplace标志的情况下处理目录合并的内容,所以如果有人能提供更多信息,那就太好了。

更新:我发现在使用--in-place时,如果rsync由于某种原因而中断,问题仍然会出现。我不完全确定rsync中目录合并的内部工作方式,所以我得出结论,它可能不是这项工作的最佳工具。相反,我编写了自己的部署函数。如果有人偶然发现这篇文章,就会发现它很有用:

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

相关内容

最新更新