1.执行字符串里的命令

  1. eval
    1. 逃脱字符
  2. exec
  3. bash -c
  4. bash -c vs eval
  5. eval vs source
  6. Notice 注意

evalexecbash -c 等命令的笔记和比较。

eval

将参数 当作shell 脚本进行执行(Execute arguments as a shell command.)

1
2
3
~$ CD="cd Desktop"
~$ eval $CD
~/Desktop$ 

逃脱字符

SQL注入SQL injection 一样,eval 可以逃脱。

1
2
3
4
5
$ cmd=("kyakya"); eval "echo hello world,"${cmd[*]}""
hello world,kyakya
$ cmd=("hacker;date"); eval "echo hello world,"${cmd[*]}""
hello world,hacker
2021年  5月 19日 水曜日 01:40:10 JST

exec

使用给定的命令,代替 当前的shell。(Replace the shell with the given command. )

1
2
3
4
5
$ bash -c "exec echo 1;echo 2"
1
$ bash -c "eval echo 1;echo 2"
1
2

示例:

  • https://github.com/panubo/docker-sshd/blob/master/entry.sh

bash -c

bash -c 文档是这样解释的:来源

If the -c option is present, then commands are read from string. If there are arguments after the string, they are assigned to the positional parameters, starting with $0.

bash -c 是开启 新的shell(subshell) ,然后执行命令的

bash -c vs eval

eval 是在 当前shell 下执行命令,所以会继承所有内容;bash -c 不继承stackoverflow

  • local variable
  • functions
  • options
  • traps
  • etc
1
2
3
4
5
6
$ cat ./test_bash.sh
bash -c "$1" # 'bash -c'命令结束时,'bash -c'所处的shell消失,本地变量也随着消失
echo "$var" 
$ bash  ./test_bash.sh var=xxx

$ # 结果为空白
1
2
3
4
5
$ cat ./test_eval.sh
eval "$1"
echo "$var"
$ bash  ./test_eval.sh var=xxx
xxx

参考:

  • https://unix.stackexchange.com/questions/124590/variable-as-command-eval-vs-bash-c

eval vs source

evalsource 的原理是一致的,区别:

  • source: Read and execute commands from the filename argument in the current shell context. [man bash](运行的一般是文本)
  • eval:Execute arguments as a shell command. (运行的一般是单个命令)

Notice 注意

当使用 evalexec 等命令创建自定义函数时,不要使用 echo 等标准输出命令

1
2
3
4
5
6
7
8
function aws(){
  echo "begin" #不要这样做
  eval "/usr/local/bin/aws $cmd_str" "$@"
}

# echo 输出的内容,将会导致管道的下一个命令启动。
$ aws xxx | grep begin
begin