TLDR
手册里面的解释:
-c
commands are read from string.
加上的原因:希望将后面的命令作为一个整体去执行。(命令在搭配 “条件执行 (&&
, ||
)” 等技巧, 可以一次执行多段命令)
分析
我们在不同的地方, 可以看到这个命令被加在 shell 命令前
- 比如 Dockerfile
FROM openjdk:12-alpine
MAINTAINER icyfenix
ENV SPRING_OUTPUT_ANSI_ENABLED=ALWAYS \
JAVA_OPTS="" \
PROFILES="default"
ADD /target/*.jar /bookstore.jar
ENTRYPOINT ["sh", "-c", "java $JAVA_OPTS -jar /bookstore.jar --spring.profiles.active=$PROFILES"]
EXPOSE 8080
- 另一个例子
sudo
> sudo echo "追加一条信息" >> test
> Permission denied
原因
在用 sudo 命令时, 希望 sudo 会给后面的 shell 命令授权, 但 sudo 仅能给后面紧接的命令授权. 如果后面还接有其他命令, 就会显示 Permission denied
, 因为后面剩余的命令并没有进行授权
而 sh -c "command ..."
可以达到这个目的, 将所有的命令作为一整条命令整体授权, 所以多个命令需要使用 sh -c
Permission denied
是因为重定向符号 >>
也属于 shell 命令, 所以虽然 echo
已经授予 root 权限, 但是 >>
并没有授权, 导致最终展示 Permission denied
(THE END)
单引号和双引号并不一样
sudo -H bash -c "echo $HOME $USER"
# 并不一样
sudo -H bash -c 'echo $HOME $USER'
Why
双引号会使用 $ 的含义, 实际上变为: sudo -H bash -c echo 实际值 实际值
详细区别
- 单引号
将字符括在单引号中会保留引号内每个字符的文字值. (单引号之间不能出现单引号,即使前面有反斜杠)
- 双引号
将字符括在双引号 ( ") 中会保留引号内所有字符的字面值,但 $、`、\
和 历史扩展时的 ! 除外. 字符$ 和 `
在双引号内保留其特殊含义(请参阅Shell Expansions)。反斜杠仅在后跟以下字符之一时才保留其特殊含义:$, `, ",\
或换行符。在双引号内,删除后面跟有这些字符之一的反斜杠。没有特殊含义的字符前面的反斜杠保持不变。双引号可以用反斜杠在双引号中引用。如果启用,将执行历史扩展,除非 !出现在双引号中的使用反斜杠进行转义。前面的 反斜杠+! 不会被删除.
sudo -H 为什么要加 -H
-H, --set-home
Request that the security policy set the HOME environment
variable to the home directory specified by the target user's
password database entry. Depending on the policy, this may be
the default behavior.
加了 -H
会使用 root 的主目录 ($HOME).
否则会将使用当前用户的主目录, 导致用户主目录中的某些文件被 root 拥有, 这可能会出现各种问题