Bash脚本实现Linux文件系统同步

Bash脚本实现Linux文件系统同步

在linux的工作环境中,不同的用户对应了不同的文件系统,我们可以通过群组等方式进行协同工作,当然这 些不同的方式也各有利弊。这篇文章主要针对各用户各自操作自己的文件系统,并在修改后 进行同步来进行协同的方式。 脚本需要帮助我们做一些机械的、简单的工作,比如将文件系统逐项比对并生成日志文件,这种工作在文件系统十分复杂的情况下工作量巨大,所以完全可以交给计算机来做。但是有些情况我们不能完全依赖于计算机,比如由于小组成员事先没有沟通好,两个用户分别把同一个文件按照自己的方案修改了,这样计算机就无法识别出我们应该保留哪个文件、删除哪个文件,而需要我们的小组成员商讨来决定。我们把这种情况叫做冲突。如果没有发生冲突,我们将文件的大小、权限、上次修改时间等信息进行比较即可,这种比较归根结底只是对字符串进行的比较,不管文件多大,计算机处理起来都非常的迅速。但当发生冲突时,我们要比较的则是两个文件的具体内容,尽管有现成的diff函数,但是对大型文件的内容比较也是十分耗费时间的。但好在这两种比较方式并不矛盾,我们对关键信息的比较既可以判断文件是否被修改,也可以判断文件是否发生了冲突,因为我们的比较不是两个文件系统进行比较,而是两个文件系统分别与日志文件进行比较;当两个文件系统的关键信息均与日志文件不同时,我们就可以认定两个用户均对该文件进行了修改,即针对这一文件发生了冲突。但是如果存在这种情况,即两用户对同一文件进行了同样的修改,或是两用户分别刷新了两文件的上次修改时间,那么这种冲突本身是无意义的,这种情况叫做*假冲突**计算机应该自行对其判断并处理,以节省人为判断的时间。这个问题解决起来也十分简单,只要diff函数没有输出就好了。


```bash
#!/bin/bash

IFS=$'\n\n'

Path_A=~/LO14_projet/a
Path_B=~/LO14_projet/b
P=.
Path_LOG=~/LO14_projet/log.log



function compare()

{
	for i in $(ls -l $1 | sed '1d')
	do 
		    name=$(echo $i | awk '{print $9}')
			Path_a=$1/$name
			Path_b=$2/$name
			j=$(ls -l $2 | grep ".*\s$name$")
			p=$3/$name
			log_A=$(echo $i $3 | awk '{printf "%s\t%s\t%s\t%s\t%s\t%s\t%s",$9,$1,$5,$6,$7,$8,$10}')
			log_B=$(echo $j $3 | awk '{printf "%s\t%s\t%s\t%s\t%s\t%s\t%s",$9,$1,$5,$6,$7,$8,$10}')
			log=$(grep "^$name\s.*\s$3$" $4)
			num_l=$(grep -n "^$name\s.*\s$3$" $4 | cut -d ':' -f 1)     #日志中该文件所在行号
			if [ -d $Path_a ] && [ -d $Path_b ]
			then
		    	compare $Path_a $Path_b $p $4

			elif [ -d $Path_a ] || [ -d $Path_b ]
			then
			    echo "There is a crash between $Path_a and $Path_b, and one of them is a directory"
				read -p "Do you want to delete one of them?(y/N)" d
				if [ $d == y ] ||[ $d == Y ]
				then
					read -p "You want to delete the file, the directory or the both(0 means delete both)?(0/d/f)" b
					if [ $b == 0 ]
					then
						rm -rf $Path_a
						rm -rf $Path_b
						sed -i ''$num_l'd' $4
					elif [ $b == d ]
					then
						if [ -d $Path_a ]
						then
						    rm -rf $Path_a
			                cp $Path_b $1
                            touch $Path_b #更新b的上次修改时间
                            k=$(ls -l $2 | grep ".*\s$name$") #更新logb
			                log_B=$(echo $k $3 | awk '{printf "%s\t%s\t%s\t%s\t%s\t%s\t%s",$9,$1,$5,$6,$7,$8,$10}') #更新logb
			                sed -i ''$num_l'c '$log_B'' $4
						else
			                rm -rf $Path_b
			                cp $Path_a $2
			                touch $Path_a #更新a的上次修改时间
			                k=$(ls -l $1 | grep ".*\s$name$")
			                log_A=$(echo $k $3 | awk '{printf "%s\t%s\t%s\t%s\t%s\t%s\t%s",$9,$1,$5,$6,$7,$8,$10}') #更新loga
			                sed -i ''$num_l'c '$log_A'' $4
			                
						fi
					elif [ $b == f ]
					then
						if [ -f $Path_a ]
						then
			                rm $Path_a
			                cp -r $Path_b $1
			                sed -i ''$num_l'c '$log_B'' $4
						else
			                rm $Path_b
			                cp -r $Path_a $2
			                sed -i ''$num_l'c '$log_A'' $4
						fi
					else
						echo 'This input is not in a right way, so the crash is not solved'	
					fi
				elif [ $d == N ] || [ $d == n ]
				then
					echo 'The crash is not solved'
				else
	                echo 'This input is not in a right way, so the crash is not solved'
				fi
			else
				if [ "$log_A" == "$log" ]
				then
					if [ "$log_B" != "$log" ]
                    then
						rm $Path_a
						cp $Path_b $1
						touch $Path_b
						k=$(ls -l $2 | grep ".*\s$name$")
						log_B=$(echo $k $3 | awk '{printf "%s\t%s\t%s\t%s\t%s\t%s\t%s",$9,$1,$5,$6,$7,$8,$10}') #更新logb
						sed -i ''$num_l'c '$log_B'' $4
					fi
				else
					if [ "$log_B" == "$log" ]
					then
						rm $Path_b
						cp $Path_a $2
						touch $Path_a
						k=$(ls -l $1 | grep ".*\s$name$")
						log_A=$(echo $k $3 | awk '{printf "%s\t%s\t%s\t%s\t%s\t%s\t%s",$9,$1,$5,$6,$7,$8,$10}') #更新loga
						sed -i ''$num_l'c '$log_A'' $4
					else
						if [ -z "$(diff $Path_a $Path_b)" ]
						then
							echo "There is a crash between $Path_a and $Path_b, but it's not a real crash"
						    rm $Path_b
						    cp $Path_a $2
						    touch $Path_a
						    k=$(ls -l $1 | grep ".*\s$name$")
						    log_A=$(echo $k $3 | awk '{printf "%s\t%s\t%s\t%s\t%s\t%s\t%s",$9,$1,$5,$6,$7,$8,$10}') #更新loga
						    sed -i ''$num_l'c '$log_A'' $4
						else
							echo "There is a crash between $Path_a and $Path_b, and both of them are files, the difference is as followed"
							diff $Path_a $Path_b
                           echo "Do you want to delete one of them?(y/N)"
							read d
							if [ $d == y ] || [ $d == Y ]
							then
								read -p "Which one do you want to delete(0 means delete both)?(0/1/2)" b
								if [ $b == 0 ]
								then
									rm $Path_a
									rm $Path_b
									sed -i ''$num_l'd' $4
								elif [ $b == 1 ]
								then
									rm $Path_a
						            cp $Path_b $1
						            touch $Path_b
						            k=$(ls -l $2 | grep ".*\s$name$")
						            log_B=$(echo $k $3 | awk '{printf "%s\t%s\t%s\t%s\t%s\t%s\t%s",$9,$1,$5,$6,$7,$8,$10}') #更新logb
						            sed -i ''$num_l'c '$log_B'' $4
								elif [ $b == 2 ]
								then
						            rm $Path_b
						            cp $Path_a $2
						            touch $Path_a
						            k=$(ls -l $1 | grep ".*\s$name$")
						            log_A=$(echo $k $3 | awk '{printf "%s\t%s\t%s\t%s\t%s\t%s\t%s",$9,$1,$5,$6,$7,$8,$10}') #更新loga
						            sed -i ''$num_l'c '$log_A'' $4
								else
									echo 'This input is not in a right way, so the crash is not solved'
								fi
							elif [ $d == N ] || [ $d == n ]
							then
								echo 'The crash is not solved'
							else
	                            echo 'This input is not in a right way, so the crash is not solved'
						fi


						fi

					fi
				fi
			fi




	done
}




compare $Path_A $Path_B $P $Path_LOG
echo "The synchronization of $Path_A and $Path_B has been completed"

``

虽然脚本很短,但由于是初学者,在写脚本的时候也出过许多问题,例如在复制文件时,被同步的文件的上次修改时间为脚本执行的时间,而原本文件的时间就再次与它不同了。我们如果对其中与日志文件时间不同的文件进行了修改,而希望脚本对其进行自动同步,那么脚本就会把这种现象判断为冲突,显然与我们的期望不同。这个问题虽然很小但不易发现,其实只要在脚本中用touch操作进行时间的刷新即可。 希望大家在评论区多多交流,可自由转载但请注明出处。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 可以使用rsync命令实现本地文件与服务器文件同步。 rsync命令可以将本地文件复制到远程服务器,也可以将远程服务器的文件复制到本地。它可以使用SSH协议进行加密传输,还支持增量同步,只传输修改过的文件。 以下是一个示例脚本,可以将本地的文件同步到远程服务器上: ```bash #!/bin/bash # 本地文件夹路径 local_dir="/path/to/local/directory" # 远程服务器信息 remote_host="remote_host" remote_user="remote_user" remote_dir="/path/to/remote/directory" # 使用rsync命令同步文件 rsync -avz --delete -e ssh $local_dir/ $remote_user@$remote_host:$remote_dir/ ``` 在这个脚本中,我们首先定义了本地文件夹的路径和远程服务器的信息。然后使用rsync命令将本地文件夹同步到远程服务器上。其中,-a选项表示使用归档模式同步文件,-v选项表示输出详细信息,-z选项表示使用压缩传输数据,--delete选项表示删除远程服务器上不存在的文件,-e ssh选项表示使用SSH协议进行加密传输。最后,我们将本地文件夹的路径和远程服务器的信息传递给rsync命令。 你可以将此脚本保存为一个.sh文件,然后在终端中执行它来同步文件。请注意替换本地文件夹路径和远程服务器信息为你自己的信息。 ### 回答2: 要实现本地文件与服务器文件的同步,可以使用shell脚本完成。 首先,需要确定同步的目录路径,包括本地和服务器的路径。 然后,可以使用rsync命令来进行文件同步。可以通过命令rsync -avz(-a表示归档模式,保留文件属性,-v表示显示详细信息,-z表示压缩传输)来同步文件。 例如,要将本地目录/path/to/local同步到服务器的目录/path/to/server,可以使用以下脚本实现: #!/bin/bash local_dir="/path/to/local" server_dir="user@server:/path/to/server" rsync -avz $local_dir $server_dir 将以上脚本保存为sync.sh文件,并给予执行权限(chmod +x sync.sh)。 然后,在终端中执行./sync.sh即可开始文件同步。 注意,需要正确配置服务器的连接信息,并确保本地和服务器的目录路径正确。 另外,可以根据实际需求添加其他参数,比如排除某些文件或目录、设置带宽限制等。 总结起来,使用shell脚本实现本地文件与服务器文件同步的步骤如下: 1. 确定同步的目录路径; 2. 编写脚本使用rsync命令进行文件同步; 3. 配置服务器的连接信息并确保目录路径正确; 4. 执行脚本开始文件同步。 这样,就可以实现本地文件与服务器文件的同步了。 ### 回答3: 实现本地文件与服务器文件同步的一种常见方法是使用shell脚本结合rsync命令。rsync是一个优秀的文件传输和同步工具,它可以帮助我们在本地文件和远程服务器文件之间实现快速、高效的同步。 首先,我们需要先安装rsync命令。在Linux系统中,可以使用包管理器直接安装,例如使用apt-get命令安装: ``` sudo apt-get install rsync ``` 接下来,我们需要编写一个shell脚本,用于实现同步功能。以下是一个简单的示例脚本: ```shell #!/bin/bash # 本地文件夹路径 local_dir="/path/to/local" # 服务器地址 server="username@remote_server:/path/to/server" # rsync命令实现同步 rsync -avz --delete $local_dir $server echo "同步完成。" ``` 在上述脚本中,我们需要设置本地文件夹路径和服务器地址。其中,`$local_dir`为本地文件夹路径,例如`/home/user/sync_folder`;`$server`为服务器地址,例如`username@remote_server:/home/user/sync_folder`。 rsync命令的选项说明: - `-a`:归档模式,保持文件属性、权限等; - `-v`:显示详细输出; - `-z`:使用压缩传输; - `--delete`:删除服务器上与本地文件夹不匹配的文件。 在脚本的最后,我们使用`echo`命令输出同步完成的提示信息。 保存脚本文件,并设置执行权限: ``` chmod +x sync.sh ``` 最后,只需执行该脚本,即可实现本地文件与服务器文件的同步: ``` ./sync.sh ``` 这样,每次执行脚本时,将会自动同步本地文件夹和远程服务器上的文件,确保它们保持同步
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值