iFr*_*cht 32 bash zsh shell-script rm deleted-files
从未想过这会发生在我身上,但你去了。 ¯\_(?)_/¯
我从错误目录中的存储库中运行了一个构建脚本,而没有先查看源代码。这是脚本Scripts/BuildLocalWheelLinux.sh
:
cd ../Dependencies/cpython
mkdir debug
cd debug
../configure --with-pydebug --enable-shared
make
cd ../../..
cd ..
mkdir -p cmake-build-local
cd cmake-build-local
rm -rf *
cmake .. -DMVDIST_ONLY=True -DMVPY_VERSION=0 -DMVDPG_VERSION=local_build
make -j
cd ..
cd Distribution
python3 BuildPythonWheel.py ../cmake-build-local/[redacted]/core.so 0
python3 -m ensurepip
python3 -m pip install --upgrade pip
[more pip install stuff]
python3 -m setup bdist_wheel --plat-name manylinux1_x86_64 --dist-dir ../dist
cd ..
cd Scripts
Run Code Online (Sandbox Code Playgroud)
危险的部分似乎是
mkdir -p cmake-build-local
cd cmake-build-local
rm -rf *
Run Code Online (Sandbox Code Playgroud)
不过仔细一想,好像也不会出错。
您应该运行此脚本的方式是cd Scripts; ./BuildLocalWheelLinux.sh
. 当我第一次运行它时,它在最后一行显示错误(我后来了解到)。我很着急,所以我虽然“也许文档已经过时了,我会尝试从项目根目录运行。所以我跑了./Scripts/BuildLocalWheelLinux.sh
。突然,vscodes 主题和缩放级别发生了变化,我的 zsh 终端配置被重置,终端字体被设置为默认值,一旦我意识到发生了什么,我就按 Ctrl+C。
还剩下一些文件,但它们没有明显的模式:
$ ls -la
total 216
drwx------ 27 felix felix 4096 May 12 18:08 .
drwxr-xr-x 3 root root 4096 Apr 15 16:39 ..
-rw------- 1 felix felix 12752 Apr 19 11:07 .bash_history
-rw-r--r-- 1 felix felix 3980 Apr 15 13:40 .bashrc
drwxrwxrwx 7 felix felix 4096 May 12 18:25 .cache
drwx------ 8 felix felix 4096 May 12 18:26 .config
drwx------ 3 root root 4096 Apr 13 21:40 .dbus
drwx------ 2 felix felix 4096 Apr 30 12:18 .docker
drwxr-xr-x 8 felix felix 4096 Apr 15 13:40 .dotfiles
-rw------- 1 felix felix 8980 Apr 13 18:10 examples.desktop
-rw-r--r-- 1 felix felix 196 Apr 19 15:19 .gitconfig
-rw-r--r-- 1 felix felix 55 Apr 16 13:56 .gitconfig.old
-rw-r--r-- 1 felix felix 1040 Apr 15 13:40 .gitmodules
drwx------ 3 felix felix 4096 May 6 10:10 .gnupg
-rw-r--r-- 1 felix felix 1848 May 5 14:24 heartbeat.tcl
-rw------- 1 felix felix 1610 Apr 13 20:36 .ICEauthority
drwxr-xr-x 5 felix felix 4096 Apr 21 16:39 .ipython
drwxr-xr-x 2 felix felix 4096 May 4 09:35 .jupyter
-rw------- 1 felix felix 161 Apr 27 14:23 .lesshst
drwx------ 3 felix felix 4096 May 12 18:08 .local
-rw-r--r-- 1 felix felix 140 Apr 29 17:54 minicom.log
drwx------ 5 felix felix 4096 Apr 13 18:25 .mozilla
drwxr-xr-x 2 felix felix 4096 Apr 13 18:10 Music
drwxr-xr-x 6 felix felix 4096 May 12 17:16 Nextcloud
-rw-r--r-- 1 felix felix 52 Apr 16 11:43 .nix-channels
-rw------- 1 felix felix 1681 Apr 20 10:33 nohup.out
drwx------ 3 felix felix 4096 Apr 15 11:16 .pki
-rw------- 1 felix felix 946 Apr 16 11:43 .profile
drwxr-xr-x 2 felix felix 4096 Apr 13 18:10 Public
drwxr-xr-x 2 felix felix 4096 May 12 18:08 .pylint.d
-rw------- 1 felix felix 1984 May 12 18:06 .pythonhist
-rw-r--r-- 1 felix felix 2443 Apr 19 13:40 README.md
drwxr-xr-x 13 felix felix 4096 May 12 18:08 repos
drwxr-xr-x 6 felix felix 4096 Apr 19 11:08 snap
drwx------ 3 felix felix 4096 May 5 15:33 .ssh
drwxr-xr-x 5 felix felix 4096 Apr 26 17:39 .stm32cubeide
drwxr-xr-x 5 felix felix 4096 May 5 15:52 .stm32cubemx
drwxr-xr-x 2 felix felix 4096 Apr 23 11:44 .stmcube
drwxr-xr-x 2 felix felix 4096 Apr 13 18:10 Templates
drwxr-xr-x 3 felix felix 4096 Apr 19 11:57 test
drwxr-xr-x 2 felix felix 4096 Apr 13 18:10 Videos
-rw------- 1 felix felix 14313 May 12 10:45 .viminfo
-rw-r--r-- 1 felix felix 816 Apr 15 13:40 .vimrc
drwxr-xr-x 3 felix felix 4096 Apr 16 12:08 .vscode
-rw-r--r-- 1 felix felix 2321 Apr 19 18:47 weird_bug.txt
-rw-r--r-- 1 felix felix 162 Apr 15 13:40 .xprofile
Run Code Online (Sandbox Code Playgroud)
.config
消失了,还有一些标准的 XDG 目录,如图片和桌面,但 .bashrc 仍然存在。.nix-channels
还在那里,但.nix-defexpr
被核弹了。
所以,这让我想到两个问题:
*
扩展,所以这里似乎发生了其他事情。Gil*_*il' 68
哎哟。你不是第一个受害者。
从您的主目录开始,例如/home/felix
,甚至在/home/felix/src
或 中/home/felix/Downloads/src
。
Run Code Online (Sandbox Code Playgroud)cd ../Dependencies/cpython
失败,因为没有../Dependencies
.
Run Code Online (Sandbox Code Playgroud)mkdir debug cd debug
您现在位于debug
您开始的目录的子目录中。
Run Code Online (Sandbox Code Playgroud)../configure --with-pydebug --enable-shared make
什么都不做,因为没有../configure
or make
。
Run Code Online (Sandbox Code Playgroud)cd ../../.. cd ..
如果您开始的目录深度不超过三层,cd debug
到了第四层,则当前目录现在是根目录。如果您从四个目录级别开始,当前目录现在是/home
.
Run Code Online (Sandbox Code Playgroud)mkdir -p cmake-build-local
这将失败,因为您无权写入/
或/home
。
Run Code Online (Sandbox Code Playgroud)cd cmake-build-local
这失败了,因为没有目录cmake-build-local
。
我们现在要……
Run Code Online (Sandbox Code Playgroud)rm -rf *
这会尝试递归删除当前目录中的每个文件,即/
或/home
。主目录按字母顺序枚举,但下面的文件按目录遍历的任意顺序枚举。它的顺序与ls --sort=none
(除非rm
出于某种原因决定使用不同的顺序)。请注意,此顺序通常不会保留在备份中,并且可以在目录中创建或删除文件时更改。
首先,几乎所有的 shell 脚本都应该set -e
在顶部附近。set -e
如果命令失败,将导致脚本中止。(如果退出状态非零,则命令失败。)set -e
不是万能药,因为在某些情况下它不会生效。但这是您可以期望的最低限度,它会在这里做正确的事情。
(此外,脚本应该以shebang行开头,以指示使用哪个 shell,例如#!/bin/sh
或#!/bin/bash
。但这对解决这个问题没有帮助。)
rm -rf *
,或类似rm -rf $foo.*
(如果$foo
结果是空的怎么办?)的变体,都是脆弱的。在这里,而不是
mkdir -p cmake-build-local
cd cmake-build-local
rm -rf *
Run Code Online (Sandbox Code Playgroud)
删除并重新创建目录会更健壮。(这不会保留目录的权限,但在这里这不是问题。)
rm -rf cmake-build-local
mkdir cmake-build-local
cd cmake-build-local
Run Code Online (Sandbox Code Playgroud)
另一种方法对于删除错误的文件更健壮,但对于要删除的丢失文件更脆弱:仅删除已知已构建的文件,通过运行make clean
具有rm
已知构建目标和已知扩展名(例如,rm *.o
可以)的命令。
Kus*_*nda 11
跟踪您的cd
调用,假设我们正在运行脚本~/Distribution/Scripts
并假设每个都cd
成功:
cd ../Dependencies/cpython
Run Code Online (Sandbox Code Playgroud)
我们现在在~/Distribution/Dependencies/cpython
.
mkdir debug
cd debug
Run Code Online (Sandbox Code Playgroud)
我们现在在~/Distribution/Dependencies/cpython/debug
.
cd ../../..
Run Code Online (Sandbox Code Playgroud)
我们现在在~/Distribution
.
cd ..
Run Code Online (Sandbox Code Playgroud)
我们现在在您的主目录中。
mkdir -p cmake-build-local
cd cmake-build-local
Run Code Online (Sandbox Code Playgroud)
我们现在在~/cmake-build-local
. 这是你运行的地方rm -rf *
。
cd ..
Run Code Online (Sandbox Code Playgroud)
我们现在回到您的主目录
cd Distribution
Run Code Online (Sandbox Code Playgroud)
我们现在在~/Distribution
.
cd ..
cd Scripts
Run Code Online (Sandbox Code Playgroud)
我们现在进入了~/Scripts
(你会因此得到一个错误,因为你比你预期的要高一级)。
接着。您尝试运行相同的脚本,但从~/Distribution
.
cd ../Dependencies/cpython
Run Code Online (Sandbox Code Playgroud)
这失败了。这让您仍然处于~/Distribution
.
mkdir debug
cd debug
Run Code Online (Sandbox Code Playgroud)
你现在在~/Distribution/debug
.
cd ../../..
Run Code Online (Sandbox Code Playgroud)
您现在在~/..
(可能在/home
)。
cd ..
Run Code Online (Sandbox Code Playgroud)
你现在很可能在/
。
cd Distribution
mkdir -p cmake-build-local
cd cmake-build-local
Run Code Online (Sandbox Code Playgroud)
这些可能由于“没有这样的文件或目录”和“权限被拒绝”而失败。
rm -rf *
Run Code Online (Sandbox Code Playgroud)
您仍在/
目录中,您的rm
命令将尝试删除整个文件系统中的每个文件。权限仅允许删除位于您具有写入权限的目录中的文件,因此您可能只会丢失/tmp
主目录中和主目录中的文件。
的命令行中列出的参数rm
将被处理的是,为了*
扩大它们(辞书,即bin
,boot
,cdrom
,dev
,etc
,等等)将然后被递归处理中列出的每个目录,并且在“目录命令”(未排序)。
你应该做的:
cd ../Dependencies/cpython
Run Code Online (Sandbox Code Playgroud)
每个单独的( ... )
子 shell 中的工作目录是该子 shell 的本地目录。cd
子外壳中的初始值不会影响“外部”环境的工作目录。其余代码使用不依赖于用户 shell 会话的初始工作目录的绝对路径名。特别注意,该rm
命令不会盲目扩展*
,而是删除通过绝对路径指定的特定目录(如果该目录不存在,这不会出现严重错误)。
如果脚本假定它是从 inside 运行的Scripts
,那么这些都不会按照脚本作者的意图执行:
cd ../Dependencies/cpython
mkdir debug
cd debug
cd ../../..
cd ..
mkdir -p cmake-build-local
cd cmake-build-local
Run Code Online (Sandbox Code Playgroud)
第一次cd
失败,第二个cd
移动到一个文件夹,那么 cd ../../..
和cd ..
可能把你上方某处你的home目录(也许在/home
目录中,其中你平时不有权做什么,所以mkdir
和随后的cd
失败)。然后*
可能扩展到您的主目录,因此对其进行rm -rf
操作,递归到内容中,这将解释删除的随机顺序(目录条目未按任何特定顺序排序)。