在 Linux 计算机上执行远程脚本期间,我没有获得正确的退出返回代码。该脚本用于检查用户是否存在。
我的脚本如下:-
#!/bin/bash
DATE=`date "+%d-%m-%Y_%H:%M:%S"`
for i in `cat /home/sandeep/server_ip_list/serverlist_New`
do
ipaddress=${i}
echo -e "\n***************" >> /tmp/userfind_${DATE}.txt
echo -e "$ipaddress" >> /tmp/userfind_${DATE}.txt
for b in `cat /home/sandeep/Project_finduser01/userslist`
do
userid=${b}
echo -e "\n" >> /tmp/userfind_${DATE}.txt
echo -n "$userid" >> /tmp/userfind_${DATE}.txt
ssh -t sandeep@${ipaddress} "grep $userid /etc/passwd > /dev/null;
if [ "$?" = "0" ];
then
echo -n " : User exsits"
else
echo -n " : User not exsits"
fi" >> /tmp/userfind_${DATE}.txt
done
done
无论用户是否存在,我总是得到下面的输出:
***************
10.25.59.12
sandeepj: User exsits
pravin: User exsits
ram: User exsits
sita: User exsits
raj.singh: User exsits
如何在服务器端操作远程退出状态代码?
答案1
代码中的主要问题是在调用$?
之前进行了扩展。ssh
这是由于引用。双引号字符串中的所有扩展都会在使用该字符串之前进行扩展。除此之外,您使用的双引号字符串还ssh
包含其他双引号部分。这些部分将是未引用的,就像abc
中未加引号的子字符串一样"123"abc"456"
。
不必尝试在远程主机上执行复杂的命令,只需让命令ssh
进入cat
文件passwd
,然后grep
:
if ssh -n "sandeep@$ipaddress" cat /etc/passwd | grep -q -F -e "$userid"
then
echo "User exists"
else
echo "User does not exist"
fi >>"/tmp/userfind_$DATE.txt"
另外,考虑使用 while 循环从用户和服务器列表中读取:
while IFS= read -r userid; do
# ...
done </home/sandeep/Project_finduser01/userslist
您还可以将最外层循环重定向到输出文件,而不是重定向每个循环echo
:
while ...; do
while ...; do
# stuff
done <userlist
done <serverlist >"/tmp/userfind_$DATE.txt"
如果您的用户列表很长,您可能只想passwd
从远程主机获取一次,然后多次查询
while ...; do
scp "sandeep@$ipaddress:/etc/passwd" passwd.tmp
while ...; do
if grep -q -F -e "$userid" passwd.tmp; then
# exists
fi
done <userlist
done <serverlist >"/tmp/userfind_$DATE.txt"
更有效的方法是将用户列表读入awk
数组,然后将passwd
文件中的用户名与它们进行匹配。这将完全摆脱最内层的循环。
用户名位于特别的文件中的字段passwd
。按照您的方法,如果您搜索 ,您将匹配marc
两者。要更仔细地匹配,请考虑使用诸如而不是与整行匹配的模式(如果您仍然使用这样做,请删除我上面介绍的模式)。marco
marc
"^$userid:"
-F
grep
passwd
您还可以使用以下命令完全避免文件解析
getent passwd "$userid" >/dev/null
如果用户存在,则返回零退出代码(成功),否则返回非零。
IE,
if ssh -n "sandeep@$ipaddress" getent passwd "$userid" >/dev/null
then
# exists
else
# does not exist
fi
不过,这将为ssh
每个用户对远程主机执行一次调用。通过不关闭每个调用之间的连接可以提高效率(下面将使连接保持打开状态一分钟):
if ssh -n -o ControlMaster=auto -o ControlPersist=1m "sandeep@$ipaddress" getent passwd "$userid" >/dev/null
then
# exists
else
# does not exist
fi
答案2
$?
为什么不像这样捕获结果代码......
ssh user@host 'cmd arg;echo $?'
如果将其分配给变量,则可以[ $n -gt 0 ]
对其进行测试。
答案3
应用建议的更改后,如果找到两种方法来实现我的结果。
第一个解决方案:使用 for 循环
#!/bin/bash/expect
DATE=`date "+%d-%m-%Y_%H-%M-%S"`
for i in `cat /root/project_finduser/serverlist`;
do
echo -e "\n*******************"
echo -e "$i"
for a in `cat /root/project_finduser/userslist`;
do
echo -e "\n"
echo -n "$a :"
if ssh "root@${i}" cat /etc/passwd | grep -w -q -F -e "$a";
then
echo "User exsits"
else
echo "User not exsits"
fi
done
done >>"/tmp/userfind_${DATE}.txt"
第二个解决方案:使用 While 循环 { 我已经通过 ssh 命令传递了 -n 选项,因为 while 循环在第一行之后停止从文件中读取参数}
#!/bin/bash
DATE=`date "+%d-%m-%Y_%H-%M-%S"`
while IFS= read -r ipaddress;
do
echo -e "\n*******************"
echo -e "$ipaddress"
while IFS= read -r userid;
do
echo -e "\n"
echo -n "$userid : "
if ssh -n "root@${ipaddress}" getent passwd "$userid" >/dev/null;
then
echo -n "User exsits"
else
echo -n "User not exsits"
fi
done < /root/project_finduser/userslist
done < /root/project_finduser/serverlist >"/tmp/userfind_${DATE}.txt"
输出 :
192.168.56.103
sandeep : 用户退出
学生:用户存在
ram : 用户不存在
sitea:用户不存在
swati : 用户退出
学生:用户存在
192.168.56.104
sandeep : 用户不存在
学生:用户存在
ram : 用户不存在
sitea:用户不存在
swati : 用户不存在
学生:用户存在