脚本位于此处:https://github.com/docker-library/ghost/blob/master/docker-entrypoint.sh
#!/bin/bash
set -e
if [[ "$*" == npm*start* ]]; then
baseDir="$GHOST_SOURCE/content"
for dir in "$baseDir"/*/ "$baseDir"/themes/*/; do
targetDir="$GHOST_CONTENT/${dir#$baseDir/}"
mkdir -p "$targetDir"
if [ -z "$(ls -A "$targetDir")" ]; then
tar -c --one-file-system -C "$dir" . | tar xC "$targetDir"
fi
done
if [ ! -e "$GHOST_CONTENT/config.js" ]; then
sed -r '
s/127\.0\.0\.1/0.0.0.0/g;
s!path.join\(__dirname, (.)/content!path.join(process.env.GHOST_CONTENT, \1!g;
' "$GHOST_SOURCE/config.example.js" > "$GHOST_CONTENT/config.js"
fi
ln -sf "$GHOST_CONTENT/config.js" "$GHOST_SOURCE/config.js"
chown -R user "$GHOST_CONTENT"
set -- gosu user "$@"
fi
exec "$@"
据我所知,它说如果您使用npm start
的某些变体将某些文件从$GHOST_SOURCE
移到$GHOST_CONTENT
,请对config.js
文件执行某些操作,链接配置文件,设置内容文件的所有权,然后以用户npm start
执行user
。否则,它只是正常运行您的命令。
细节是我难以理解的,因为bash中有很多我以前从未见过的东西。所以我有很多问题。
for dir in "$baseDir"/*/ "$baseDir"/themes/*/; do
在上文中,为什么他们同时指定/*/
和/themes/*/
?不应该/*/
包含主题吗?由于某种原因,*
不是通配符吗?
targetDir="$GHOST_CONTENT/${dir#$baseDir/}"
在上面,变量扩展中#
的重点是什么?
tar -c --one-file-system -C "$dir" . | tar xC "$targetDir"
在上面,这会以某种方式节省时间吗?为什么不使用像rsync这样的东西?我理解-C
的要点,但为什么-c
和--one-file-system
?
sed -r '
s/127\.0\.0\.1/0.0.0.0/g;
s!path.join\(__dirname, (.)/content!path.join(process.env.GHOST_CONTENT, \1!g;
' "$GHOST_SOURCE/config.example.js" > "$GHOST_CONTENT/config.js"
这个sed
命令有什么作用?我知道它是替代品,但为什么"$GHOST_SOURCE/config.example.js" > "$GHOST_CONTENT/config.js"
作为结束?
ln -sf "$GHOST_CONTENT/config.js" "$GHOST_SOURCE/config.js"
在上面,这个符号链接有什么意义?如果两个文件都已存在,为什么还要尝试将它们相互链接?
set -- gosu user "$@"
在上面,调用set
没有args的是什么?
我希望不是太多。我觉得为这些问题单独提出一个问题会特别多,因为它们都是相互关联的。
答案 0 :(得分:2)
for dir in "$baseDir"/*/ "$baseDir"/themes/*/; do
在上文中,为什么他们同时指定
/*/
和/themes/*/
?不该'吨/*/
包含主题?由于某种原因,*
不是通配符吗?
themes /是第一场比赛,但是主题/ * /不是,所以你需要第二个条目来包含主题的内容。
targetDir="$GHOST_CONTENT/${dir#$baseDir/}"
在上面,变量扩展中#的重点是什么?
它从$ dir中删除$ baseDir前缀。例如:
bash$ dir=/home/bmitch/data/docker
bash$ echo $dir
/home/bmitch/data/docker
bash$ echo ${dir#/home/bmitch}
/data/docker
默认情况下,可能不会在每台计算机上安装rsync,tar相当普遍。 -c是创建,vs提取和--one-file-system避免tar继续到外部挂载点(nfs,符号链接到root等)。tar -c --one-file-system -C "$dir" . | tar xC "$targetDir"
在上面,这会以某种方式节省时间吗?为什么不使用像 rsync的?我理解-C的重点,但为什么-c和--one-file-system?
sed -r ' s/127\.0\.0\.1/0.0.0.0/g; s!path.join\(__dirname, (.)/content!path.join(process.env.GHOST_CONTENT, \1!g; ' "$GHOST_SOURCE/config.example.js" > "$GHOST_CONTENT/config.js"
这个sed命令有什么作用?我知道它是一个替代品,但为什么呢 " $ GHOST_SOURCE / config.example.js" > " $ GHOST_CONTENT / config.js"作为 结束?
config.example.js是输入(sed的最后一个arg),config.js是输出(在>之后)。所以需要config.example.js,将ip地址从127.0.0.1更改为0.0.0.0,有效地监听所有接口/ ip,而不是仅仅在内环上。 sed的后半部分是将__dirname中的path.join参数更改为process.env.GHOST_CONTENT。
ln -sf "$GHOST_CONTENT/config.js" "$GHOST_SOURCE/config.js"
在上面,这个符号链接有什么意义?为什么要尝试链接它们 如果两个文件都已存在,那么它们会互相生效吗?
$ GHOST_SOURCE / config.js被替换为(-f)并带有$ GHOST_CONTENT / config.js的链接。符号链接提供对另一个实际文件的文件名引用,因此将有两个名称,但是数据的一个副本,这意味着在这种情况下您将只有一个配置。
set -- gosu user "$@"
在上面,没有args的调用set会怎么做?
这会将$ 1,$ 2,... $ n的值更改为$ 1 = gosu,$ 2 =用户,$ 3 =旧$ 1,$ 4 =旧$ 2 ...,实际上是将gosu和用户添加到传递给脚本的参数的开头。 - 确保set不会将$ @中的任何值解释为自身的标志。