jus*_*oSo 3 linux shell debian
当我在环境中执行以下脚本时Debian 12 live
,我发现在这个脚本中无法执行umount /mnt
。提示是/mnt : target is busy
. 但是,脚本执行后,我能够sudo umount /mnt
在命令行上成功执行。我已经给这个脚本添加了777权限。问题是什么?
#!/usr/bin/bash\nset +x\ncurrent_path=$(pwd)\necho $current_path\nhdstr=/dev/mmcblk0\nhdstr1=${hdstr}p1\nhdstr2=${hdstr}p2\nhdstr3=${hdstr}p3\n\nroot_path=/mnt\nboot_path=${root_path}/boot\ngrub_path=${boot_path}/grub\nefi_path=${boot_path}/efi\n\nlib64_path=${root_path}/lib64\nbin_path=${root_path}/bin\nlib_path=${root_path}/lib\n\necho "debug:function definition"\n \nexecute_command() {\n local command=$1\n eval "$command"\n local status=$?\n if [ $status -eq 0 ]; then\n echo "run the cmd:$command success"\n else\n echo "failed to run the cmd:$command" \n exit 1\n fi\n}\n\nadd_env_for_chroot() {\n echo "add env for chroot"\n execute_command "sudo mkdir -p ${lib64_path}"\n execute_command "sudo ln -s ${lib_path} ${lib64_path}"\n execute_command "sudo cp ${lib_path}/* ${lib64_path}/ -nra"\n}\n\n\nchange_root() {\n echo "change root"\n #execute_command "sudo mount --rbind /dev /mnt/dev"\n #execute_command "sudo mount --rbind /proc /mnt/proc"\n #execute_command "sudo mount --rbind /sys /mnt/sys"\n execute_command "sudo mount -t proc proc /mnt/proc"\n execute_command "sudo mount -t sysfs sys /mnt/sys"\n execute_command "sudo mount -o bind /dev /mnt/dev"\n execute_command "sudo mount --bind /run /mnt/run"\n add_env_for_chroot\n\n \n cat << EOF | sudo chroot ${root_path}\n grub-install --target=x86_64-efi /dev/mmcblk0 --force --recheck --efi-directory=/boot/efi \n exit\nEOF\n}\n\ncreate_fstab() {\n echo "create fstab"\n UUID1=$(sudo blkid | grep '^/dev/mmcblk0p1' | awk -F 'UUID="' '{print $2}' | awk -F '"' '{print $1}')\n UUID2=$(sudo blkid | grep '^/dev/mmcblk0p2' | awk -F 'UUID="' '{print $2}' | awk -F '"' '{print $1}')\n UUID3=$(sudo blkid | grep '^/dev/mmcblk0p3' | awk -F 'UUID="' '{print $2}' | awk -F '"' '{print $1}')\n #\xe8\xbf\x99\xe9\x87\x8c\xe4\xb8\x8d\xe6\x9b\xbf\xe6\x8d\xa2sda\n devName="\\/dev\\/mmcblk0p1"\n UUIDStr="UUID=$UUID1"\n execute_command "sed -i \\"s/${devName}/${UUIDStr}/g\\" /mnt/etc/fstab"\n \n devName="\\/dev\\/mmcblk0p2"\n UUIDStr="UUID=$UUID2"\n execute_command "sed -i \\"s/${devName}/${UUIDStr}/g\\" /mnt/etc/fstab"\n \n devName="\\/dev\\/mmcblk0p3"\n UUIDStr="UUID=$UUID3"\n execute_command "sed -i \\"s/${devName}/${UUIDStr}/g\\" /mnt/etc/fstab"\n}\n\npartition_format_mount() {\n echo "begin to part"\n ####partition####\n sudo /sbin/parted ${hdstr} mklabel gpt\n sudo /sbin/parted ${hdstr} <<EOT 1>/dev/null 2>/dev/null || exit 1\n rm 1\n rm 2\n rm 3\n rm 4\n mkpart primary fat32 1MiB 200MiB\n set 1 esp on\n mkpart primary ext4 200MiB 8200MiB\n mkpart primary ext4 8200MiB 100%\n quit\nEOT\n echo ""\n ####format####\n echo "begin to format"\n #execute_command "sudo partx ${hdstr} 1>/dev/null"\n execute_command "sudo /sbin/mkfs.fat -F32 ${hdstr1} 1>/dev/null"\n execute_command "sudo /sbin/mkfs.ext4 ${hdstr2} 1>/dev/null"\n execute_command "sudo /sbin/mkfs.ext4 ${hdstr3} 1>/dev/null"\n \n execute_command "sudo /sbin/fsck.vfat -v -a -w ${hdstr1} 1>/dev/null"\n execute_command "sudo /sbin/fsck.ext4 ${hdstr2}"\n execute_command "sudo /sbin/fsck.ext4 ${hdstr3}"\n ####mount####\n execute_command "sudo mkdir -p ${root_path}"\n execute_command "sudo mount ${hdstr3} ${root_path} 1>/dev/null"\n execute_command "sudo mkdir ${boot_path} -p"\n execute_command "sudo mount ${hdstr2} ${boot_path} 1>/dev/null"\n execute_command "sudo mkdir ${efi_path} -p"\n execute_command "sudo mount ${hdstr1} ${efi_path} 1>/dev/null"\n echo "end part"\n}\n\ninstall_os(){\n echo "begin to install grub"\n execute_command "sudo mkdir -p ${grub_path}"\n execute_command "sudo cp ${current_path}/grub_CRA.cfg ${grub_path}/grub.cfg"\n\n\n #execute_command "sudo cp ${current_path}/x86_64-efi /usr/lib/grub/ -raf" #issue1\n execute_command "sudo cp \\"${current_path}/bzImage\\" ${boot_path}/" #2024-1-19 \xe4\xbf\xae\xe6\x94\xb9bzImage\xe8\xb7\xaf\xe5\xbe\x84\n execute_command "sudo cp \\"${current_path}/initrd.img-6.4.0-rt8\\" ${boot_path}" #2024-1-19 \xe4\xbf\xae\xe6\x94\xb9initrd\xe8\xb7\xaf\xe5\xbe\x84\n execute_command "sudo cp \\"${current_path}/rootfs.tar.gz\\" ${root_path}"\n cd ${root_path}\n execute_command "sudo tar -vxf rootfs.tar.gz"\n execute_command "echo \\"y\\" | sudo rm rootfs.tar.gz"\n echo "begin to changerooot" \n change_root\n create_fstab\n \n echo "start to umount" \n execute_command "sudo umount ${hdstr1} 1>/dev/null"\n execute_command "sudo umount ${hdstr2} 1>/dev/null"\n execute_command "sudo umount /mnt/run"\n #execute_command "sudo umount /mnt/{proc,sys,dev}"\n execute_command "sudo umount /mnt/proc"\n execute_command "sudo umount /mnt/sys"\n execute_command "sudo umount /mnt/dev"\n #cat << EOF | sudo chroot ${root_path}\n #echo "To successfully umount /mnt, I don't know why, but it is useful." \n #exit\n#EOF\n execute_command "sync"\n#==========================my question in here=============================\n sudo umount /mnt \n#==========================================================================\n# execute_command "sudo umount ${hdstr3} 1>/dev/null"\n #sudo /sbin/fsck.vfat -a ${hdstr1}\n #sudo /sbin/fsck.ext4 -a ${hdstr2}\n #sudo /sbin/fsck.ext4 -a ${hdstr3}\n execute_command "sync" \n}\n\nmainFunc(){\n echo "start to burn"\n partition_format_mount\n install_os \n}\n\nmainFunc\n
Run Code Online (Sandbox Code Playgroud)\n
roa*_*ima 20
您已经获得了相当于cd /mnt
脚本上方的内容,因此您位于尝试卸载的目录中。
这里还需要考虑其他一些大问题:
脚本中的几乎每个命令都在 下运行sudo
,因此请考虑删除所有这些调用sudo
并要求脚本本身在 下运行sudo
。
#!/bin/bash
if [ "$(id -u)" -ne 0 ]
then
echo "Please re-run with sudo" >&2
exit 1
fi
Run Code Online (Sandbox Code Playgroud)
或者甚至让脚本自动重新运行sudo
:
#!/bin/bash
if [ "$(id -u)" -ne 0 ]
then
echo "Re-running with sudo" >&2
exec sudo "$0" "$@"
exit 1
fi
Run Code Online (Sandbox Code Playgroud)
您将命令存储在变量中。这可能会导致各种与引用相关的问题,而您使用eval
. 变量用于数据,函数用于命令:
execute_command() {
if "$@"
then
echo "ran $1 successfully" >&2
else
echo "failed to run $1" >&2
exit 1
fi
}
execute_command sudo umount /mnt/proc
Run Code Online (Sandbox Code Playgroud)
但实际上,这可以简单地通过在第一行设置-e
(或者可能是-ex
,该-x
标志启用逐行跟踪)或使用set -e
and 可能set -x
不久之后来实现。例如,
#!/bin/bash -ex
echo "this line succeeds"
echo "the next line will fail"
false
echo "the script has already stopped so you will not see this"
exit 0
Run Code Online (Sandbox Code Playgroud)
您没有对任何变量进行双引号。这意味着每当您使用它们时,它们都会受到分裂和通配符的影响。
“我已经为此脚本添加了 777 权限” - 可能不需要允许其他用户编辑此脚本,因此不要放弃该权利。最多允许其他用户运行该脚本:
chmod u=rwx,go=rx ./your_script # Replace "./yourscript" with the script path
Run Code Online (Sandbox Code Playgroud)