[英]bash shell script for loop
I have a bash shell script that loops through a server list file to verify a user exists on that server.我有一个 bash shell 脚本循环遍历服务器列表文件以验证用户是否存在于该服务器上。 My question is, I want the script to echo out which servers the user exists on before executing command: sleep;
我的问题是,我希望脚本在执行命令之前回显用户所在的服务器:sleep; clear;
清除; main_sec <(this is a function) problem is as soon as that condition is met, it just echo's the first server met then executes code.
main_sec <(this is a function) 问题是只要满足该条件,它就会回显第一个遇到的服务器然后执行代码。 How do i echo it all out then execute the code?
我如何将其全部回显然后执行代码?
echo -e "${YELLOW}Checking if user account exists on any of the servers above${NONE}"
readarray -t lines < servers.txt
for server in "${lines[@]}"; do
ssh -q -o StrictHostKeyChecking=no $server "egrep "^$username" /etc/passwd" &>/dev/null
if [ $? -eq 1 ]; then
continue
fi
if [ $? -eq 0 ]; then
echo -e "${RED}User account $username already exists on $server, Must choose a unique username before proceeding. Returning to menu...${NONE}"
sleep 5; clear; main_sec
fi
done
What you want is to save a match and use it later.您想要的是保存匹配并在以后使用它。 You can use a variable for that:
您可以为此使用变量:
return_menu=
for ...; do
if ssh ...; then
...
else
echo >&2 "User account $username already exists on $server, Must choose a unique username before proceeding. Returning to menu..."
return_menu=return_menu
fi
fi
done
if [[ $return_menu != '' ]]; then
sleep 5
clear
main_sec
fi
Here is a corrected version of your code with all my advice from below:这是您的代码的更正版本,其中包含以下我的所有建议:
#username=...
return_menu=
echo "${YELLOW}Checking if user account exists on any of the servers above$NONE"
readarray -t lines < servers.txt
for server in "${lines[@]}"; do
if printf 'getent passwd %q >/dev/null' "$username" |
ssh -q -o StrictHostKeyChecking=no "$server" bash -s; then
continue
else
printf >&2 '%s\n' \
"${RED}User account $username already exists on $server." \
"You must choose a unique username before proceeding." \
"${NONE}Returning to menu..."
return_menu=return_menu
fi
done
if [[ $return_menu != '' ]]; then
sleep 5
clear
main_sec
exit 0
fi
Some code mistakes you can avoid:您可以避免的一些代码错误:
$?
$?
won't change! Your second execution of $?
你第二次执行
$?
will be 0
as it's if
's return code (unless you change your code) Instead of the syntax command; if [ $? ]
将是
0
,因为它是if
的返回码(除非你改变你的代码)而不是语法command; if [ $? ]
command; if [ $? ]
command; if [ $? ]
, use: command; if [ $? ]
,使用:
if ssh ...; then
...
else
...
fi
https://mywiki.wooledge.org/BashPitfalls#pf44 https://mywiki.wooledge.org/BashPitfalls#pf44
[
[
[
or test
is the POSIX test command. [
或test
是 POSIX 测试命令。 It can do simple tests on files and strings.它可以对文件和字符串进行简单的测试。 In bash, you should use the more powerful
[[
instead and ban [
for sake of consistency.在 bash 中,您应该使用更强大的
[[
代替并禁止[
以保持一致性。 [[
can do pattern matching, is faster and safer to use. [[
可以做模式匹配,使用起来更快更安全。
http://mywiki.wooledge.org/BashGuide/TestsAndConditionals http://mywiki.wooledge.org/BashGuide/TestsAndConditionals
http://mywiki.wooledge.org/BashFAQ/031 http://mywiki.wooledge.org/BashFAQ/031
main_sec
will launch something else, and you don't want lines further down the script continue executing once you finish so you should add an exit afterwards to be sure you really terminate when main_sec
finishes main_sec
将启动其他内容,并且您不希望脚本在完成后继续执行,因此您应该在之后添加一个退出以确保您在main_sec
完成时真正终止
egrep
is deprecated egrep
已弃用Use grep -E
if needed (not needed here)如果需要,请使用
grep -E
(此处不需要)
grep... > /dev/null
grep... > /dev/null
If you only want the return code, use grep -q
.如果您只想要返回码,请使用
grep -q
。 This avoid scanning all the input when you only want to know if a match is there.当您只想知道是否存在匹配时,这可以避免扫描所有输入。 It helps for larger inputs.
它有助于更大的输入。
getent
instead of /etc/passwdgetent
而不是 /etc/passwd Instead of scanning /etc/passwd, you should use getent
which is designed for it It also covers domain accounts, if it helps.而不是扫描 /etc/passwd,你应该使用为它设计的
getent
它还包括域帐户,如果它有帮助的话。
By convention, we capitalize environment variables ( PAGER
, EDITOR
, ..) and internal shell variables ( SHELL
, BASH_VERSION
, ..).按照惯例,我们将环境变量(
PAGER
、 EDITOR
、..)和内部 shell 变量( SHELL
、 BASH_VERSION
、..)大写。 All other variable names should be lower case.所有其他变量名称应为小写。 Remember that variable names are case-sensitive;
请记住,变量名是区分大小写的; this convention avoids accidentally overriding environmental and internal variables.
此约定避免意外覆盖环境和内部变量。
echo
with options flagsecho
与选项标志一起使用echo
outputs a string. echo
输出一个字符串。 echo
has many portability problems, and should never be used with option flags. echo
有很多可移植性问题,不应该与选项标志一起使用。 Consider printf
instead: printf 'name: %s\n' "$name"
.考虑
printf
代替: printf 'name: %s\n' "$name"
。
http://wiki.bash-hackers.org/commands/builtin/echo http://wiki.bash-hackers.org/commands/builtin/echo
http://cfajohnson.com/shell/cus-faq.html#Q0b http://cfajohnson.com/shell/cus-faq.html#Q0b
http://www.in-ulm.de/~mascheck/various/echo+printf http://www.in-ulm.de/~mascheck/various/echo+printf
In this case, you are using echo -e '$RED... $NONE'
.在这种情况下,您使用的是
echo -e '$RED... $NONE'
。
I'm guessing it's because RED='\e[31m' NONE='\e(B\e[0m'
我猜这是因为
RED='\e[31m' NONE='\e(B\e[0m'
If you used these values instead, you could use the colors without echo
's -e
:如果您改用这些值,则可以使用 colors 而不使用
echo
的-e
:
RED=$'\e[31m' NONE=$'\e(B\e[0m'
Here, username
may be set by someone who has ill intent to values such as ; rm -rf /
在这里,
username
可能由对值有恶意的人设置,例如; rm -rf /
; rm -rf /
. ; rm -rf /
。 Once launched on you ssh servers, this could be disastrous.一旦在 ssh 服务器上启动,这可能是灾难性的。 Even if you have set the username in the code yourself, you don't know if the code won't be changed in the future to some form of user-defined value, so you should protect your code against this while you still can by escaping special characters before passing them to
ssh
.即使您自己在代码中设置了用户名,您也不知道将来代码是否不会更改为某种形式的用户定义值,因此您应该保护您的代码免受这种情况的影响,同时您仍然可以通过escaping 特殊字符,然后将它们传递给
ssh
。 There are many ways to do that, and one is:有很多方法可以做到这一点,其中一种是:
printf 'getent passwd %q >/dev/null' "$username" | ssh -q -o StrictHostKeyChecking=no "$server" bash -s
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.