9

我正在尝试为 useradd 命令制作简单的功能,并快速提高我糟糕的 shell 编程技能。

useradd -m -g [initial_group] -G [additional_groups] -s [login_shell] [username]

现在我有点不确定如何使用可选参数。经过一些谷歌搜索,我认为可能对此有所了解,只需要围绕代码进行操作。

我不确定的一件事是逻辑,我很好奇你们将如何写这篇文章。我相信它会比我可以一起破解的更好。


以下是我将如何尝试设置我的函数参数,对于登录 shell 和初始组,我希望它们具有通用默认值。

arg1 - userName, required
arg2 - loginShell, optional (default: /bin/bash)
arg3 - initGroup, optional (default: users)
arg4 - otherGroups, optional (default: none)

这是一些关于我如何构建它的蹩脚的伪代码。

function addUser( userName, loginShell, initGroup, otherGroups){
// Not how I would go about this but you should get the point
  string bashCmd = "useradd -m -g ";

// Adding the initial user group
  if(initGroup == null){
    bashCmd += "users";
  } else {
    bashCmd += initGrop;
  }

// Adding any additional groups
  if(otherGropus != null){
    bashCmd += " -G " + otherGroups;
  }

  if(loginShell == null){
    bashCmd += " -s /bin/bash " + userName;
  } else {
    bashCmd += " -s " + loginShell + " " + userName;
  }
}

这些是我要经过的链接

http://tldp.org/HOWTO/Bash-Prog-Intro-HOWTO-8.html

将参数传递给 Bash 函数

如何编写带有可选输入参数的 bash 脚本?

在此处文档中使用函数

4

3 回答 3

14

您可能会发现${parameter:+word}扩展很有用。来自Bash 参考手册

如果parameter为 null 或未设置,则不替换任何内容,否则替换word的扩展。

所以:

function addUser {
    useradd -m ${2:+-s "$2"} ${3:+-g "$3"} ${4:+-G "$4"} "$1"
}

请注意,如果任何参数包含有趣的字符(如空格、美元符号或其他 shell 元字符),此函数会正确处理引用。如果您尝试将命令字符串拼凑在一起,则正确引用这些片段要困难得多。如果这只是供您个人短期使用并且您知道输入是安全的,那可能并不重要。但是,如果脚本或函数打算以 root 身份运行并且没有非常仔细地处理其输入,那么最好不要留下脚本或函数。

于 2012-11-03T05:52:24.673 回答
10

@rob mayoff 的回答是完成此任务的最简单方法,但我想我会尝试将您的伪代码转换为真正的 shell 语法,以指出一些习惯于“真正”编程语言的人的标准陷阱。先说三点一般注意事项:

  • 不同的shell 有不同的功能,所以如果您需要任何bash 扩展,请使用bash(即使用命令启动脚本#!/bin/bash或运行它)。bash如果您只使用基本的 Bourne shell 功能和语法,请改用 sh (#!/bin/shsh命令)运行它。如果你不知道,假设你需要 bash。
  • 在为以后执行构建命令时,您可能会遇到各种解析异常(请参阅BashFAQ#050:我正在尝试将命令放入变量中,但复杂的情况总是失败!)。最好的方法通常是将其构建为数组,而不是字符串。'当然,数组是 bash 扩展,而不是基本的 shell 功能......
  • 在 shell 语法中,空格很重要。例如,在 commandif [ -n "$2" ]; then中,分号后的空格是可选的(分号前也可以有一个空格),但所有其他空格都是必需的(没有它们,命令将执行完全不同的操作)。此外,在作业中,等号周围不能有空格,或者(再次)它会做一些完全不同的事情。

考虑到这一点,这是我对该功能的看法:

addUser() {
# The function keyword is optional and nonstandard, just leave it off. Also,
# shell functions don't declare their arguments, they just parse them later
# as $1, $2, etc

bashCmd=(useradd -m)
# you don't have to declare variable types, just assign to them -- the
# parentheses make this an array. Also, you don't need semicolons at the
# end of a line (only use them if you're putting another command on the
# same line). Also, you don't need quotes around literal strings, because
# everything is a string by default. The only reason you need quotes is to
# prevent/limit unwanted parsing of various shell metacharacters and such.

# Adding the initial user group
if [ -z "$3" ]; then
# [ is actually a command (a synonym for test), so it has some ... parsing
# oddities. The -z operator checks whether a string is empty (zero-length).
# The double-quotes around the string to be tested are required in this case,
# since otherwise if it's zero-length it'll simply vanish. Actually, you
# should almost always have variables in double-quotes to prevent accidental
# extra parsing.
# BTW, since this is a bash script, we could use [[ ]] instead, which has
# somewhat cleaner syntax, but I'm demonstrating the difficult case here.
    bashCmd+=(-g users)
else
    bashCmd+=(-g "$3")
    # Here, double-quotes here are not required, but a good idea in case
    # the third argument happens to contain any shell metacharacters --
    # double-quotes prevent them from being interpreted here. -g doesn't
    # have any shell metacharacters, so putting quotes around it is not
    # necessary (but wouldn't be harmful either).
fi

# Adding any additional groups
if [ -n "$4" ]; then
    bashCmd+=(-G "$4")
fi

# Set the login shell
if [ -z "$2" ]; then
    bashCmd+=(-s /bin/bash "$1")
else
    bashCmd+=(-s "$2" "$1")
fi

# Finally, run the command
"${bashCmd[@]}"
# This is the standard idiom for expanding an array, treating each element
# as a shell word.
}
于 2012-11-03T17:24:48.007 回答
0

谷歌为ABS获取许多复杂的样本

function addUser{
userName=$1;
loginShell=$2;
initGroup=$3
otherGroups=$4;

  args=(-m -g);

// Adding the initial user group
  if [[ $initGroup == '' ];then
    args+=(users);
  else 
    args+=("$initGrop");
  fi;

# Adding any additional groups
  if [[ $otherGroups != '' ]];then
    args+=(-G "$otherGroups");
  fi;

  if [[ $loginShell == '' ]];then
    args+=(-s /bin/bash "$userName");
  else
    args+=(-s "$loginShell" "$userName");
  fi;
  useradd "${args[@]}"
}

代码未检查,但我希望我不会错过任何东西

于 2012-11-03T05:50:03.767 回答