就像很多球队一样,我们现在有很多人在家工作。这些远程客户端位于防火墙后面(我们不控制防火墙),而且它们没有静态IP地址。简而言之,我们不能直接将SSH带入这些客户端。但是,客户端可以将SSH放入我们的服务器。(由于其他原因,已在所有客户端和服务器上设置了硬化SSH。)
我们的要求是在每个客户端上保持一组文件(在几个不同的目录中)保持同步,并有效地做到这一点。我试图避免让每个客户端每秒钟运行一个rsync命令。当服务器上的任何相关文件被更改时,最好通知客户端。
此外,我们的实现只能使用SSH、rsync、inotify工具以及bash或Python (以及awk、cut等工具)。具体来说,我们不能使用NextCloud、OwnCloud、SyncThing、SeaFile等。
服务器上唯一打开的传入端口是用于SSH的,我们希望维护或更新的唯一包是发行版存储库中的核心包。
我们的想法是让每个客户端建立一个指向服务器的反向SSH隧道。然后服务器可以运行这样的脚本:
#!/bin/bash
while true; do
inotifywait -r -e modify,attrib,close_write,move,create,delete /path/to/source/folder
for port_user in "$(netstat -Wpet | grep "ESTABLISHED" | grep 'localhost.localdomain:' | grep 'sshd:' | cut -d ':' -f2-3 | cut -d ' ' -f1,4)"; do
uport=$(echo $port_user | cut -d ' ' -f1)
uu=$(echo $port_user | cut -d ' ' -f2)
sudo -u $uu rsync -avz -e "ssh -p $uport -i /home/$uu/.ssh/id_ed25519" /path/to/source/folder $uu@localhost:/path/to/destination/folder
done
done我在寻求反馈。首先,上面的bash脚本可以改进或清理吗?例如,我似乎不得不使用太多的cut语句。
EDIT:以下是对roaima的优秀问题和评论的答复。
netstat -Wpetl
tcp 0 0 localhost.localdomain:22222 0.0.0.0:* LISTEN myuser 42137 8381/sshd: myuser#!/bin/bash
synchost=sync.example.com
syncpath="path/to/sync/folder"
uu=$(logname)
uport=222222 #hard code per client device
# initial sync upon connecting:
rsync -avzz -e "ssh -i /home/$uu/.ssh/id_ed25519" /"$syncpath"/ $uu@$synchost:/"$syncpath"
# loop until script is stopped when user logs out
while true; do
inotifywait -r -e modify,attrib,close_write,move,create,delete /"$syncpath"
rsync -avzz -e "ssh -i /home/$uu/.ssh/id_ed25519" /"$syncpath"/ $uu@$synchost:/"$syncpath"
done还有一个随需应变脚本,用户可以在任何时候运行强制同步.这是上面没有while循环的脚本。
syncpath="path/to/sync/folder"
while true; do
inotifywait -r -e modify,attrib,close_write,move,create,delete /"$syncpath"
netstat -Wpetl | grep "LISTEN" | grep 'localhost.localdomain:' | grep 'sshd:' | while read proto rq sq local remote state uu inode prog
do
uport=${local#*:}
sudo -u $uu rsync -avzz -e "ssh -p $uport -i /home/$uu/.ssh/id_ed25519" /"$syncpath"/ $uu@localhost:/"$syncpath"
done
done这是个好建议。但是,一些有效的rsync更新可能运行的时间比平均时间长得多。您能否建议一种适当的方法来处理正常和必要的长rsync更新,同时也处理更新期间客户端断开连接的罕见情况?
我有一个想法,一种方法,可以解决超时,以及(大部分)比赛条件,以非常非常简单的方式。首先,每个用户登录时的初始客户端同步应该负责长期运行的更新操作。因此,服务器端同步操作时间不会有如此长的右尾。我们可以优化超时参数和睡眠时间,并使用如下方法:
syncpath="path/to/sync/folder"
while true; do
inotifywait -r -e modify,attrib,close_write,move,create,delete /"$syncpath"
netstat -Wpetl | grep "LISTEN" | grep 'localhost.localdomain:' | grep 'sshd:' | while read proto rq sq local remote state uu inode prog
do
uport=${local#*:}
timeout 300s sudo -u $uu rsync -avzz -e "ssh -p $uport -i /home/$uu/.ssh/id_ed25519" /"$syncpath"/ $uu@localhost:/"$syncpath"
done
sleep 90
netstat -Wpetl | grep "LISTEN" | grep 'localhost.localdomain:' | grep 'sshd:' | while read proto rq sq local remote state uu inode prog
do
uport=${local#*:}
timeout 900s sudo -u $uu rsync -avzz -e "ssh -p $uport -i /home/$uu/.ssh/id_ed25519" /"$syncpath"/ $uu@localhost:/"$syncpath"
done
done最后一条评论。为rsync命令显示的参数不是最终的。建议是值得赞赏的,但我们也打算花费一些时间来评估rsync命令的所有选项。
发布于 2020-09-08 08:51:51
许多想法
netstat -Wpet并简化sudo -u ${user}操作。ssh -R 20202:localhost:22 centralserver ),我无法从netstat | grep | grep | cut ...行获得端口和用户组合。netstat -Wpet \ grep“已建立”grep sshd: tcp 036中央服务器:ssh客户端:37226已建立的根238622975 15198/sshd: roaima,因此我无法有效地测试对脚本的可能更改。你想在这里看到什么?inotifywait完成后更改了第二个文件,则在另一个文件被更改之前,它可能不会传播到所有目标系统。解决方法可能是侦听单个inotifywait实例中的事件,并在每个事件上运行rsync传输集。但是,取决于更新的频率,这可能会使客户端的网络连接饱和。ssh/rsync到客户端的超时,以便如果它们在尝试传输时断开连接,那么最终不会阻塞其他所有人bash代码片段,您可以用变量操作(%、#和/操作符)替换cut语句,同时读取-r proto recvq sendq localaddrport状态用户inode pidprogram do localaddr="${localaddrport%:*}“localport="${localaddrport#*:}”${ foreignaddrport %:*}“foreignport="${foreignaddrport#*:}”pid="${pidprogram%/*}“program=”${pidprogram##*}“program=”;<(netstat -Wpet _ grep '\.*/sshd:') )> program="${program%:}“回声外部地址= $foreignaddr和端口= $foreignport”echo "PID = $pid,Program= $program“echo”名称=$namenetstat命令的预期输出,则可以使用awk简化行处理。https://unix.stackexchange.com/questions/608380
复制相似问题