假设我想为chroot
命令编写包装器,可以设置工作目录,否则保留chroot
语义。因此语义应该是:
chroot.sh <chroot-dir> <working-dir> <command> [arg]...
我天真的尝试是:
#!/bin/sh
chroot_dir=$1
working_dir=$2
shift 2
chroot "$chroot_dir" sh -c "cd $working_dir; $*"
但这无法正确处理:
chroot.sh /path/to/chroot /tmp touch 'filename with space'
我不知道应该如何正确实施它。只用bash可以吗?
在我的 CentOS 6 系统上chroot
命令不支持设置工作目录。在其他系统上可能并非如此。
答案1
处理这个问题的方法是将参数作为引用列表传递后通过以下方式调用的命令chroot
:
chroot "$chroot_dir" sh -c 'cd "$1" && shift && "$@"' - "$working_dir" "$@"
这是一个有效的示例,包括普通环境的设置chroot
。
设置
# Where
chroot="$HOME/chroot"
# Directory structure
mkdir -p -m755 "$chroot"/{bin,dev,lib,tmp}
chmod 1777 "$chroot"/tmp
# Shell
cp -a /bin/dash "$chroot"/bin/sh
# Devices
cp -a /dev/{null,tty} "$chroot"/dev
# Libraries
cp -p $(ldd /bin/dash | sed 's/^.*=> //' | awk '!/vdso/ {print $1}' ) "$chroot"/lib/
# Demonstration executable
cat >"$chroot"/bin/args <<'EOF'
#!/bin/sh
#
echo "Got $# arg(s): $*"
echo "CWD: $(pwd)"
printf '> %s <\n' "$@"
EOF
chmod a+x "$chroot"/bin/args
执行(应用程序args
)
working_dir=/tmp
chroot "$chroot" /bin/sh -c 'cd "$1" && shift && "$@"' - "$working_dir" args 'one two' three
输出
Got 2 arg(s): one two three
CWD: /tmp
> one two <
> three <
正如您从输出中看到的,空格和参数都被正确保留。
答案2
最后我得出以下解决方案:
#!/bin/sh
chroot_dir=$1
working_dir=$2
shift 2
printf -v CMDS " %q" "$@"
chroot "$chroot_dir" sh -c "cd \"$working_dir\";$CMDS"
答案3
这似乎做你所追求的:
#!/bin/bash
chroot_dir="$1"
shift
working_dir="$1"
shift
cmd="$@"
chroot "${chroot_dir}" sh -c "cd ${working_dir} ; ${cmd}"
请注意 /tmp 仅以脚本开头:
# ls /tmp
chroot.sh
我有一个 chroot at /mnt/foo
,它是一个绑定安装/
:
# /tmp/chroot.sh /mnt/foo /tmp touch '"filename with spaces"'
现在请注意文件filename with spaces
存在:
# ls -1 /tmp
chroot.sh
'filename with spaces'