我应该使用参数还是导出环境变量?

时间:2017-01-03 10:38:16

标签: linux bash shell

我总是每天使用参数开发我的shell脚本,甚至在开发一些自动化脚本时。但是,最近我尝试了一种不同的方法,将环境变量导出到我的脚本中。

#!/bin/bash

: ${USER?"Requires USER"}
: ${FIRST_NAME?"Requires FIRST_NAME"}
: ${LAST_NAME?"Requires LAST_NAME"}
: ${EMAIL?"Requires EMAIL"}

set -x

setup_git_account(){
  su - "${USER}" -c "git config --global user.name '${FIRST_NAME} ${LAST_NAME}'"
  su - "${USER}" -c "git config --global user.email '${EMAIL}'"
}

setup_git_account

这确保了更小的代码,在初始化所有必需变量时可以轻松检查,并且一旦在外部声明所有变量,就可以更好地理解脚本正在做什么。

export USER='john' && export FIRST_NAME='John' && export LAST_NAME='Doe' && export EMAIL='john.doe@email.com' && setup_git_account.sh

如果使用接收参数实现,可以用这样表示:

setup_git_account.sh --user 'john' --firstname 'John' --lastname 'Doe' --email 'john.doe@email.com'

但是,最后一个,需要更多行代码来实现getopts切换案例,检查传递的参数值等。

无论如何,我知道我们已经习惯了第二种方法,但我认为第一种方法也有几个好处。如果所提出的方法之间存在任何不利之处,我想向您倾听更多信息。我应该使用哪一个?

谢谢!

4 个答案:

答案 0 :(得分:2)

有点偏离主题, static char TOUCH_DEVICE[256] = "/dev/uinput"; struct uinput_user_dev touch_uidev; struct input_event moveev[2]; struct input_event touchev; static int touchfd = -1; // Opening device if((touchfd = open(TOUCH_DEVICE, O_WRONLY | O_NONBLOCK)) == -1) { printf("cannot open touch device %s\n", TOUCH_DEVICE); exit(EXIT_FAILURE); } printf("Registering event types...\n"); if(ioctl(touchfd, UI_SET_EVBIT, EV_SYN) < 0) die("error: ioctl"); if(ioctl(touchfd, UI_SET_EVBIT, EV_ABS) < 0) die("error: ioctl"); if(ioctl(touchfd, UI_SET_ABSBIT, ABS_X) < 0) die("error: ioctl"); if(ioctl(touchfd, UI_SET_ABSBIT, ABS_Y) < 0) die("error: ioctl"); memset(&touch_uidev, 0, sizeof(touch_uidev)); snprintf(touch_uidev.name, UINPUT_MAX_NAME_SIZE, "uinput-mouse"); touch_uidev.id.bustype = BUS_USB; touch_uidev.id.vendor = 0x1; touch_uidev.id.product = 0x1; touch_uidev.id.version = 1; touch_uidev.absmin[ABS_X] = 0; touch_uidev.absmax[ABS_X] = 640; touch_uidev.absmin[ABS_Y] = 0; touch_uidev.absmax[ABS_Y] = 480; if(write(touchfd, &touch_uidev, sizeof(touch_uidev)) < 0) die("error: write"); if(ioctl(touchfd, UI_DEV_CREATE) < 0) die("error: ioctl"); printf("Mouse fd opened successfully.\n"); //Injecting events memset(moveev, 0, sizeof(moveev)); moveev[0].type = EV_ABS; moveev[0].code = ABS_X; moveev[0].value = x; moveev[1].type = EV_ABS; moveev[1].code = ABS_Y; moveev[1].value = y; if(write(touchfd, moveev, sizeof(moveev)) < 0) die("error: write"); memset(&touchev, 0, sizeof(touchev)); touchev.type = EV_SYN; touchev.code = 0; touchev.value = 0; if(write(touchfd, &touchev, sizeof(touchev)) < 0) die("error: write"); 的环境变量的调用语法可以更短,不需要bash

export

答案 1 :(得分:1)

您的所有值都不是可选的;我只想使用位置参数。

: ${1?"Requires USER"}
: ${2?"Requires FIRST_NAME"}
: ${3?"Requires LAST_NAME"}
: ${4?"Requires EMAIL"}

sudo -u "$1" git config --global user.name "$2 $3" user.email "$4"

为用户提供以任意顺序指定值的方式只是一种不必要的复杂化。

您只需使用

调用脚本即可
setup_git_account.sh 'john' 'John' 'Doe' 'john.doe@email.com'

重新考虑名字和姓氏是否需要单独的参数。无论如何,它们被脚本组合成git config的单个参数;只需将名称作为单个参数。

setup_git_account.sh 'john' 'John Doe' 'john.doe@email.com'

(根据需要对脚本进行适当的更改)。

答案 2 :(得分:0)

我从不使用你的方法。我认为使用参数没有任何缺点。这是使用参数的常用方法,如果您使用的是longopts,则可以进行自我描述。 在我看来,如果您需要不同脚本中的数据,env vars是一种解决方案。

在您不允许更改环境的系统上运行此类脚本时可能会遇到问题。

答案 3 :(得分:0)

我使用guide对您的变量进行了参数化,我后来写了一段时间,甚至添加了--help

此解决方案接受环境变量和选项(将胜过变量):

while getopts e:f:hl:u:-: arg; do
  case "$arg" in
    e )  EMAIL="$OPTARG" ;;
    f )  FIRST_NAME="$OPTARG" ;;
    h )  do_help ;;
    l )  LAST_NAME="$OPTARG" ;;
    u )  USER_NAME="$OPTARG" ;;
    - )  LONG_OPTARG="${OPTARG#*=}"
         case $OPTARG in
           email=?* )   EMAIL="$LONG_OPTARG" ;;
           first*=?* )  FIRST_NAME="$LONG_OPTARG" ;;
           help* )      do_help ;;
           last*=?* )   LAST_NAME="$LONG_OPTARG" ;;
           user=?* )    USER_NAME="$LONG_OPTARG" ;;
           * ) echo "Illegal option/missing argument: --$OPTARG" >&2; exit 2 ;;
         esac ;;
    * )  exit 2 ;; # error messages for short options already given by getopts
  esac
done
shift $((OPTIND-1))

HELP=" - see ${0##*/} --help"
: ${USER_NAME?"Requires USER_NAME$HELP"}
: ${FIRST_NAME?"Requires FIRST_NAME$HELP"}
: ${LAST_NAME?"Requires LAST_NAME$HELP"}
: ${EMAIL?"Requires EMAIL$HELP"}

su - "$USER_NAME" -c "git config --global user.name '$FIRST_NAME $LAST_NAME'"
su - "$USER_NAME" -c "git config --global user.email '$EMAIL'"

请注意,我将$USER更改为$USER_NAME以避免与您的本地环境发生冲突($USER 您的用户名在本地Linux系统上!)< / p>

您还可以从系统中提取用户的全名:

FULL_NAME="$(getent passwd |awk -v u="$USER_NAME" -F: '$1 == u { print $5 }')"

(我认为没有理由将FIRST_NAME和LAST_NAME分开;你对Jean Claude Van Damme做了什么?他们只是一起使用。另请注意,并非所有用户都会在passwd文件中使用全名。)

这使用do_help来显示--help输出。这是一个如何看的例子(我把它放在脚本的顶部,所以有人只是阅读它可以得到概要;它不在上面的代码块中,因为我想阻止该块获得滚动条):

do_help() { cat <</help
Usage: ${0##*/} [OPTIONS]
  -u USER_NAME,  --user=USER_NAME
  -f FIRST_NAME, --firstname=FIRST_NAME
  -l LAST_NAME,  --lastname=LAST_NAME
  -e EMAIL,      --email=EMAIL
Each option may also be passed through the environment as e.g. $EMAIL

Code taken from https://stackoverflow.com/a/41515444/519360
/help
}