在同一个 shell 脚本中挂载和卸载会导致错误

Kum*_*mar 5 shell tar mount shell-script unmounting

我需要tar在单个 shell 脚本中挂载一个卷、挂载卷的内容并卸载该挂载的卷。

所以我编码为,

$ cat sample.sh
sudo mount -o loop Sample.iso /tmp/mnt
cd /tmp/mnt
tar-cvf /tmp/sample.tar *
sudo umount /tmp/mnt
Run Code Online (Sandbox Code Playgroud)

我得到了错误 umount: /tmp/mnt: device is busy.

所以我检查了

$ lsof /tmp/mnt
Run Code Online (Sandbox Code Playgroud)

它输出当前的“sh”文件。所以我说服自己,/tmp/mnt忙于当前的脚本(在这种情况下,sample.sh)。

在同一个脚本中 (mount, tar, unmount) 有什么办法吗?

PS:脚本完成后,我可以卸载 /tmp/mnt 卷。

Luc*_*ini 15

您需要退出目录才能卸载它,如下所示:

#!/bin/bash
sudo mount -o loop Sample.iso /tmp/mnt
cd /tmp/mnt
tar -cvf /tmp/sample.tar *
#Got to the old working directory. **NOTE**: OLDPWD is set automatically.
cd $OLDPWD
#Now we're able to unmount it. 
sudo umount /tmp/mnt
Run Code Online (Sandbox Code Playgroud)

这就对了。

  • @LucianoAndressMartini @Kusalananda 提供了最简单的方法:`( cd /tmp/mnt && tar -cvf /tmp/sample.tar * )` 不需要显式cd,因为一旦tar 命令退出子shell 就会终止。需要明确的是,我并不是在争辩说 `cd /tmp` 比返回它来的地方更好;我只是反对将 `cd /` 作为一种不好的做法。 (4认同)
  • 没有理由使用`$OLDPWD` 或`cd -` 或类似的东西。只是`cd /`。`cd` 调用只影响运行脚本的子 shell,我们只需要离开 `/tmp/mnt`。任何目标都可以,因为一旦脚本退出,我们将始终位于脚本启动时所在的任何目录中。 (2认同)

Kus*_*nda 11

该设备“忙碌”,因为您刚刚cd进入它。您不能卸载当前工作目录的分区(任何进程,在本例中为 shell)。

你的脚本:

sudo mount -o loop Sample.iso /tmp/mnt
cd /tmp/mnt
tar -cvf /tmp/sample.tar *
sudo umount /tmp/mnt
Run Code Online (Sandbox Code Playgroud)

没有同样问题的修改脚本:

sudo mount -o loop Sample.iso /tmp/mnt
( cd /tmp/mnt && tar -cvf /tmp/sample.tar * )
sudo umount /tmp/mnt
Run Code Online (Sandbox Code Playgroud)

由于cd发生在子shell中,因此不会影响其外部的环境,此时的当前目录umount将是您执行脚本时所在的任何位置。

这是一个很常见的shell构造,即做

( cd dir && somecommand )
Run Code Online (Sandbox Code Playgroud)

它比尝试在cd某个地方然后再返回要干净(和清晰)得多,尤其是在一个脚本的过程中必须进入多个目录时。

使用&&它也意味着如果由于cd某种原因失败,则不会执行该命令。在您的脚本中,如果mount失败,您仍然会创建一个tar空 (?) 目录的存档,例如,这可能不是您想要的。

使用以下-C标志的较短变体tar

sudo mount -o loop Sample.iso /tmp/mnt
tar -cvf /tmp/sample.tar -C /tmp/mnt .
sudo umount /tmp/mnt
Run Code Online (Sandbox Code Playgroud)

这使得在将当前目录 ( )添加到存档之前tarcd内部进行/tmp/mnt。但是请注意,这会导致隐藏文件或文件夹也将添加到存档中。