我有一个 bash 脚本需要以 root 身份运行才能完成一项任务,在这种情况下,它是让验证器拍摄 Helium 区块链的快照。
我已编辑 /etc/sudoers 文件,以允许我以 root 身份运行此脚本。这工作正常。
useraccount ALL=(ALL:ALL) NOPASSWD:/home/useraccount/validator_data/snapshotmaker.sh
脚本中的命令如下:
sudo docker exec validator miner snapshot take /var/data/$dtt
此后,该命令会生成如下文件'30-10-2021T233752.bin“”。
我的下一步是获取此文件并将其复制到 IPFS,以便我可以共享它。执行此操作的命令是:
ipfs files cp /ipfs/$(ipfs add -Q $localfile) $ip
目前我收到以下错误:
Error: no IPFS repo found in /root/.ipfs. please run: 'ipfs init'
这是因为当配置在我的用户帐户中时,它试图以 root 身份运行它。
我曾尝试在脚本执行过程中切换帐户,但似乎会失败。
所以我的问题是如何以我的原始用户身份从根脚本中运行 IPFS 命令。
我的 Bash 脚本:
#!/bin/bash
dt=$(date '+%d-%m-%YT%H%M%S');
dtt="${dt}.bin"
a='/var/data/'
c="${a}${dt}.bin"
echo "${c}"
sudo docker exec validator miner snapshot take /var/data/$dtt
localfile="/home/useraccount/validator_data/${dt}.bin"
echo "LocalFile: ${localfile}"
ip=" /Helium/Snapshots/2021/${dt}.bin"
echo "IPFS Location: ${ip}"
sleep 2
if [ -f "$localfile" ]; then
echo "$localfile exists."
sudo chown useraccount $localfile
whoami
su - useraccount
whoami
ipfs files cp /ipfs/$(ipfs add -Q $localfile) $ip
#ipfs files cp /ipfs/$(ipfs add -Q <local-file>) "/Helium/Snapshots/2021/<dest-name>"
else
echo "$localfile does not exist."
fi
输出如下:
/var/data/31-10-2021T005728.bin
ok
LocalFile: /home/useraccount/validator_data/31-10-2021T005728.bin
IPFS Location: /Helium/Snapshots/2021/31-10-2021T005728.bin
/home/useraccount/validator_data/31-10-2021T005728.bin exists.
root
然后它就死机了。如果我删除该su
行,就会出现本文开头提到的根本问题。
希望有人可以帮忙。
答案1
我做了一个“试运行”测试,没有docker
和你在里面做什么,也没有ipfs
。方法应该经过一些调整后即可使用真实程序为您工作。
scrip
以普通用户身份运行 shellscript ,而不是使用sudo
。编辑脚本,将我的演示中的“测试人员”更改为您的用户名。
sudo
使用以下方式编辑无需密码的精确命令行visudo
:$ LANG =C sudo tail -n2 /etc/sudoers %tester ALL=NOPASSWD: /usr/sbin/docker exec validator miner snapshot take /var/data/tmpfil %tester ALL=NOPASSWD: /usr/bin/chown tester /home/tester/validator_data/tmpfil
- 对于 sudo 操作来说,拥有一个固定的文件名称非常重要。之后可以根据时间赋予一个名称。
- 检查docker可执行文件的位置(可能不在
/usr/sbin
)。
我修改后的脚本scrip
:
#!/bin/bash
if [ "$(whoami)" != "tester" ]
then
echo "run as 'tester'"
exit
fi
dt=$(date '+%d-%m-%YT%H%M%S');
dtt="${dt}.bin"
a='/var/data/'
c="${a}${dt}.bin"
echo "${c}"
sudo /usr/sbin/docker exec validator miner snapshot take /var/data/tmpfil
if [ -f "/home/tester/validator_data/tmpfil" ]; then
ls -l "/home/tester/validator_data/tmpfil"
sudo /usr/bin/chown tester "/home/tester/validator_data/tmpfil"
mv "/home/tester/validator_data/tmpfil" "/home/tester/validator_data/${dt}.bin"
localfile="/home/tester/validator_data/${dt}.bin"
echo "LocalFile: ${localfile}"
ls -l "${localfile}"
ip=" /Helium/Snapshots/2021/${dt}.bin"
echo "IPFS Location: ${ip}"
sleep 2
echo "$localfile exists."
whoami
/usr/local/bin/ipfs files cp /ipfs/$(/usr/local/bin/ipfs add -Q $localfile) $ip
#ipfs files cp /ipfs/$(ipfs add -Q <local-file>) "/Helium/Snapshots/2021/<dest-name>"
else
echo "$localfile does not exist."
fi
假装是命令行的脚本docker
:
#!/bin/bash
if [ "$EUID" == "0" ]
then
echo "docker's world" > "/home/tester/validator_data/tmpfil"
chown root:root "/home/tester/validator_data/tmpfil"
echo "ok"
else
echo "run with sudo"
fi
演示运行:
tester@lenovo-v130:~$ LANG=C ./scrip
/var/data/01-11-2021T051748.bin
ok
-rw-r--r-- 1 root root 15 Nov 1 05:17 /home/tester/validator_data/tmpfil
LocalFile: /home/tester/validator_data/01-11-2021T051748.bin
-rw-r--r-- 1 tester root 15 Nov 1 05:17 /home/tester/validator_data/01-11-2021T051748.bin
IPFS Location: /Helium/Snapshots/2021/01-11-2021T051748.bin
/home/tester/validator_data/01-11-2021T051748.bin exists.
tester
./scrip: line 34: ipfs: command not found
./scrip: line 34: ipfs: command not found
答案2
所以我的问题是如何以我的原始用户身份从根脚本中运行 IPFS 命令。
sudo su - useraccount -c COMMAND
答案3
首先,您需要为您的脚本创建一个 sudo 配置,在此示例中,我们将其放置在/etc/sudoers.d
具有权限的环境中440
:
Cmnd_Alias CMDS = /opt/bin/docker_example.sh
User_Alias CMDUSERS = bac0n
CMDUSERS ALL=(ALL) NOPASSWD: CMDS
Defaults!CMDS !requiretty
我们将脚本命名为docker_example.sh
,如 sudo 示例所示:
#!/bin/bash
# Exit immediately on non-zero exit status.
set -e
((EUID != 0)) && {
echo This script should run as root.
exit 1
}
[[ ${SUDO_USER+ } ]] && \
user_account=$SUDO_USER || user_account=$(id -nu)
printf -v bin_file \
'%(%d-%m-%YT%H%M%S)T.%s' -1 bin
local_file=$HOME/validator_data/$bin_file
ipfs_file=/Helium/Snapshots/2021/$bin_file
printf '
Bin File: %s
Local File: %s
IPFS File: %s
' "$bin_file" "$local_file" "$ipfs_file"
docker exec validator miner snapshot take "/var/data/$bin_file"
sleep 2
[[ -f $local_file ]] || {
echo File does not exist: "$local_file"
exit 1
}
chown $user_account "$local_file"
#
# su $user_account -c 'echo whoami: $1, su: $(id -nu)' _ $(id -nu)
#
su $user_account -c 'ipfs files cp "/ipfs/$(ipfs add -Q "$1")" "$2"' _ "$local_file" "$ipfs_file"
现在您应该能够使用 sudo 将此脚本添加到 crontab,并且它应该使用 NOPASSWD 运行。
$ sudo crontab -u bac0n -e
# min hour dom month dow command
* * * * * sudo /opt/bin/docker_example.sh > /dev/null 2>&1