一次惨痛的教训后,向各位shell高手求一个Linux mv命令的同名拦截函数

环境:操作系统:CentOS 7.6;shell:zsh 5.0.2

晚上搬砖到凌晨2点多时,一时糊涂,竟然莫名其妙地在shell命令行中敲下了如下让我后悔莫及的命令:

mv /* /www/wwwroot

从而将系统根目录下面的/bin、/etc、/sbin、/usr、/var、/root、/home等目录移动到了/www/wwwroot目录下,于是导致很多命令都无法正常执行。整个人都懵了的情况之下,手忙脚乱中又关闭了连线中的shell终端会话窗口,于是再也连不上服务器了。

由于根本连不上服务器,之后找云服务商帮忙也表示爱莫能助,只能重装系统。

这次教训过于惨痛,痛定思痛之余,为了以后避免类似事件,想编写一个拦截mv命令的同名函数,当发现mv后面输入的是/*或/bin、/etc、/sbin、/usr、/var、/root、/home时,echo一个警告信息出来,然后退出执行。

但我发现在条件表达式中无法匹配到参数“/*”中的星号*,因为星号*在作为参数输入之前已被展开,因此实际上输入的参数是星号*展开后的值。

由于在下水平有限,这里请教一下各位shell高手,能否根据上述要求,编写一个拦截mv命令的同名函数。

诚挚感谢!

阅读 1.2k
评论
    6 个回答
    • 717

    还有一个教训是,你最好在云上,数据放到数据盘里面,数据盘记得重装是不影响的,还可以挂到其他虚机上面,但是放到系统盘,就没办法,能搞出来,但是,非常折腾。
    仅说说你要实现的功能,因为shell默认开启了通配符扩展。
    你先自己搞一个脚本,然后用alias添加别名,在别名里面,用set -f关掉,你在脚本里面,就可以拿到输入的参数了,然后你就可以做自己的参数匹配。
    简单如下

    alias mv2="set -f; /path/to/mv2.sh"

    在mv2.sh 里面,你用$1-n拿到的参数,就是带*号而不是解析后的参数了。
    简单如下

    set -f
    echo $1
    
    set +f
    echo $1

    在真正把参数传递给真正执行的命令时候,记住要重新开启通配符匹配功能,具体你可以试试。

      你需要的不是一个安全的mv,而是一个健壮的备份恢复系统
      即使你现在实现了一个安全的mv,那还有安全的rm和安全的cp甚至安全的vim,事实上,即使你有一个百分百安全的操作系统,云服务商也有可能会丢掉你的数据。
      所以异地备份+一个快速部署恢复,才是比较可靠的选择

        你应该想着平时用普通账号登录,而不是 root。否则不止 mv,rm 也很危险。

          如果服务器在身旁的话,可以使用centos的救援模式,需要装有centos系统的u盘或光盘,在救援模式里可以使用简单的命令,可以把根目录移回来,系统就正常的了

            • 257

            你下次可先试试,用引导光盘,进救援模式,很将原系统盘挂载,要借助chroot 和mv 把误迁移的数据移回去:)

            PS:有兴趣也可以在虚拟机上先测试下

              • 2
              • 新人请关照

              云主机这种情况很好处理, 临时买一个按时计费新机器, 把久机器的系统硬盘挂载到临时机, mv 回去。卸载盘。 启动旧机器测试。文件不丢,基本上就OK的。
              还有定时快照有必要的。

                撰写回答

                登录后参与交流、获取后续更新提醒

                相似问题
                推荐文章