前言
(如果你不想听我 BB, 可以直接跳转到 最后一段: #结论.)
先解释一下为什么要这么做.
我原本用的是 clash + 澳洲 VPS (V2Ray), 奈何最近 GFW 相当疯狂, 从每个星期一封进步到现在的一天一封, 甚至上午换 IP 下午封, 强度这么大, 这谁吃得消? 我尝试使用 Oracle 提供的 API 检测封杀并自动切换 IP, 但是我的功力不到家, 还有就是 Oracle 的文档太过迷惑, 我愣是没写出来.
閱讀全文 在 Openwrt 上使用迷雾通透明代理局域网流量(如果你不想听我 BB, 可以直接跳转到 最后一段: #结论.)
先解释一下为什么要这么做.
我原本用的是 clash + 澳洲 VPS (V2Ray), 奈何最近 GFW 相当疯狂, 从每个星期一封进步到现在的一天一封, 甚至上午换 IP 下午封, 强度这么大, 这谁吃得消? 我尝试使用 Oracle 提供的 API 检测封杀并自动切换 IP, 但是我的功力不到家, 还有就是 Oracle 的文档太过迷惑, 我愣是没写出来.
閱讀全文 在 Openwrt 上使用迷雾通透明代理局域网流量環境:
Docker + WordPress, 用官方默認的 Apache 驅動, 不是 fpm.
因為 PhpRedis 不屬於 PHP 內置的模塊, 而 PHP 內置了一個 Predis 又太慢太蛋疼, 所以要重新構建 Docker Image 為 PHP 添加 Redis 模塊支持.
為了添加這個 Redis 模塊, 我特別做了一些搜索, 發現網上清一色的全部是 本教程只適合 fpm 版本云云. 我個人認為這是一種迷思啊, 因為不論是用 php-fpm 還是 apache + php-mod 應該都和 php 的插件沒有太多關係吧. 所以雖然上面環境說的是 wordpress-apache , 用 wordpress-fpm 的朋友照著這個教程做也沒差.
mkdir /tmp/build cd /tmp/build
# 添加 Memcached 支持 cat > /tmp/build/Dockerfile << EOF FROM wordpress:latest RUN apt-get update RUN apt-get install -y libz-dev libmemcached-dev && \ pecl install memcached && \ docker-php-ext-enable memcached && \ RUN rm -rf /tmp/pear && \ apt-get clean EOF
# 添加 Redis 支持 cat > /tmp/build/Dockerfile << EOF FROM wordpress:latest RUN pecl install -o -f redis && \ docker-php-ext-enable redis RUN rm -rf /tmp/pear EOF
關於 Memcached vs Redis… 這個網上都可以搜到吧. 我的意見是, 兩者都能給一個 WordPress 小博客提供相當不錯的 Object Cache. 效能的話, Redis 略勝一籌, 但是要求專門開一個 Redis 容器. 而 Memcached 安裝好之後直接用就可以了. 所以還是根據服務器的配置來選吧.
docker build -t wordpress_extended .閱讀全文 WordPress Docker 優化: 添加 PhpRedis、Memcached 支持
如果你並不是想要做異地組網, 而是想要在 VPS 上跑 (Nginx/Caddy/Apache) + WP + V2Ray, 那麼你其實用不著這麼複雜. 你只需要看這篇文章就可以了.
(這篇博文主要是討論一個沒多少人做過的方案的可行性, 所以你會看到後面還有一大通廢話; 作為教程本文是不合格的, 如果想要尋找教程請出門右轉谷歌搜索. )
閱讀全文 WordPress + Cloudflared + V2ray 異地組網並隱藏流量警告: 我只是一個正在學習 Docker 的中學生,
一切在生產環境嘗試本文所述技巧所導致的損失都是自作自受.
有的時候, Docker 鏡像更新了, 但是容器並沒有更新, 你想要用更新過後的鏡像來部署容器; 奈何你並沒有像 Portainer 這樣的 GUI 介面, 你早就不記得當初部署容器時執行的指令了, 碰到這種情況應該怎麼辦?
下文便以更新 Portainer 為例來演示簡單的無縫切換鏡像.
第一步當然是要先拉取更新的鏡像.
docker pull portainer/portainer-ce:latest
接著, 使用 rekcod 這個工具來獲取部署容器時輸入的命令.
$ docker run --rm -i -v /var/run/docker.sock:/var/run/docker.sock nexdrew/rekcod <container> # 樹莓派玩家 # docker run --rm -v /var/run/docker.sock:/var/run/docker.sock nexdrew/rekcod:3.0.0arm # 為該命令設別名 # alias rekcod="docker run --rm -v /var/run/docker.sock:/var/run/docker.sock nexdrew/rekcod:3.0.0arm"
短暫刪除舊的容器, 然後部署上新的.
$ docker stop <container> $ docker rm <container> $ <執行 rekcod 得到的結果>
至此, 新的容器就部署好了, 而當機時間不會超過幾秒鐘👌
最後別忘了刪除掉舊的鏡像喔.
假設當初用來 Build 鏡像的 Dockerfile 已經遺失, 可以用 dfimage 這個神器來從鏡像中提取 Dockerfile 用於構建.
$ docker run -v /var/run/docker.sock:/var/run/docker.sock --rm alpine/dfimage <image> # 為該命令設別名 # alias dfimage="docker run -v /var/run/docker.sock:/var/run/docker.sock --rm alpine/dfimage "
恢復出來後就可以愉快的繼續玩耍啦~ 但是要注意, 很多時候不是恢復出來就可以用的, 因為涉及到 Reverse Engineering, 恢復出來的文件基本是和原來的 Dockerfile 不一樣的. 因此還是建議好好保存 Dockerfile.
sudo apt update -y && sudo apt upgrade -y sudo snap install rpi-imager
2. 從 清華大學鏡像 下載 Arm64 的 PiOS_Lite.
3. 使用 Rpi-Imager 刷入鏡像. 使用 Ubuntu 自帶的磁碟工具擴展 rootfs 容量到最大. (也可以不要, 最新版本的系統第一次開機會自動 Resize Partitions 將 / 分區擴到最大)
4. 在 boot 目錄下新建空白的 ssh 文件
cd ~/media/boot/ touch ssh
0. 連線到樹莓派.
ssh [email protected] #raspberry
# 補充: 以下 2 到 4 步可以用下面的命令替換 (快速執行)
pubkey="YOUR SSH PUBKEY"
sudo su
mkdir ~/.ssh
echo $pubkey >> ~/.ssh/authorized_keys
chmod 700 ~/.ssh
chmod 644 ~/.ssh/authorized_keys
cp /etc/ssh/sshd_config /etc/ssh/sshd_config.bak
sed -i 's/^#PermitRootLogin/PermitRootLogin/' /etc/ssh/sshd_config
sed -i 's/^#PubkeyAuthentication/PubkeyAuthentication/' /etc/ssh/sshd_config
sed -i 's/^#AuthorizedKeysFile/AuthorizedKeysFile/' /etc/ssh/sshd_config
sed -i 's/^PermitRootLogin.*/PermitRootLogin prohibit-password/' /etc/ssh/sshd_config
sed -i 's/^PubkeyAuthentication.*/PubkeyAuthentication yes/' /etc/ssh/sshd_config
systemctl restart sshd.service
systemctl status sshd.service
exit
# 設置密碼 sudo passwd pi sudo passwd root
2. 修改登錄方式
# 配置 SSH 登錄 su cd ~/ mkdir .ssh chmod 700 .ssh vi /root/.ssh/authorized_keys # 複製你的公鑰進去 chmod 644 /root/.ssh/authorized_keys vi /etc/ssh/sshd_config # 配置ssh登錄
2. 在 sshd_config
中修改以下幾句.
LoginGraceTime 10m # afk達10min自動登出 PermitRootLogin prohibit-password # 只允許root用ssh登錄 MaxAuthTries 6 # 最多允許三次錯誤登錄嘗試 MaxSessions 10 # 最多允許三個client同時登錄 PubkeyAuthentication yes # 開啓公鑰登錄 AuthorizedKeysFile .ssh/authorized_keys #開啓公鑰 PasswordAuthentication no # 不允許任何用戶使用密碼登錄 PermitEmptyPasswords no # 不允許任何空密碼用戶登錄
3. 繼續執行一下語句, 確定 status 沒有報錯之後登出.
systemctl restart sshd.service systemctl status sshd.service exit
4. 重新以 root 身份登錄.
5. 更新/設置系統
apt update && apt upgrade -y # 更新系統 (不推荐) #rpi-update # 更新 Kernel #reboot #rpi-eeprom-update # 更新 Bootloader #raspi-config # 6 -> A7 -> E1 # 設置系統 raspi-config # 重新登錄 exit
更新: 不推荐执行 rpi-update 更新系统, 因为这行命令实际上是拉取了最新的不稳定的 Linux 内核. 如果已经执行了这个命令的同学, 可以考虑执行以下命令回滚内核:sudo apt install --reinstall libraspberrypi0 libraspberrypi-{bin,dev,doc} raspberrypi-bootloader raspberrypi-kernel
具体的内容参考这篇官方文档: 点我跳转树莓派官网
設置系統的部分自己選擇, 畢竟選項和提示都寫的很清楚.
我是比較喜歡開啟 Overlay Filesystem + ReadOnly Boot Partition 的, 前者就是一個開機一鍵還原, 後者是防止突然斷電破壞 boot 分區. 我覺得這兩個都比較實用, 建議全部設置完之後開啟.
至於語言 (Locale) 設定, 我喜歡把所有 zh 開頭的都勾上, 然後選用 zh_CN.UTF8, 可以保證亂碼不會出現.
至於測試的話, 只要 mkdir 測試
, 然後 ls
一看看一看中文是否正常顯示就可以了.
# 安裝基本軟件 apt install vim git make wget -y # 設置 UFW apt install ufw -y ufw allow from 192.168.10.1/24 ufw default deny ufw enable ufw status # 設置 NTP 服務 apt install ntpdate -y echo '@reboot ntpdate 192.168.10.1' >> /etc/crontab # 設置 開機掛載硬盤 mkdir /mnt/data mount /dev/sda1 /mnt/data blkid # 複製顯示的 uuid 和 type echo 'UUID=2e2e58b1-8fe8-4f5c-9478-f5eef65c5aa5 /mnt/data ext4 defaults 1 2' >> /etc/fstab mount -a # 確定沒有報錯! # 開機掛載網絡硬盤 sudo apt install -y curlftpfs echo '@reboot curlftpfs -o rw,allow_other ftp://username:[email protected]/ /media/ftpdrive' >> /etc/crontab # 安裝 ZSH & OH MY ZSH apt install zsh -y sh -c "$(wget https://raw.github.com/ohmyzsh/ohmyzsh/master/tools/install.sh -O -)" # 重啟 reboot
簡單的解釋一下為什麼我上面是這樣配置:
/media/pi/...
, 我不想要它, 所以已經把它 unmount 掉了.2. 安裝 Docker
# 安裝 Docker curl -fsSL https://get.docker.com | bash -s docker --mirror Aliyun docker -v systemctl enable docker.service systemctl enable containerd.service # 將 Docker 數據卷掛到外接硬盤 systemctl stop docker systemctl stop containerd # 第一次裝系統使用這個方法 rsync -av /var/lib/docker /mnt/data/ rsync -av /var/lib/containerd /mnt/data/ rm -r /var/lib/docker /var/lib/containerd # 如果重裝過系統想要恢復數據 # mv /var/lib/docker /var/lib/docker.bak # mv /var/lib/containerd /var/lib/containerd.bak ln -s /mnt/data/docker /var/lib/docker ln -s /mnt/data/containerd /var/lib/containerd systemctl start docker systemctl start containerd
3. 安裝 Docker-compose ( 使用 pip3 因為 Github 上下載不到針對 Arm 的二進制包 )
apt install python3-venv python3-pip apt install libffi-dev # 構建環境, 完成後可以卸載掉 pip3 install docker-compose docker-compose -v # 刪除構建緩存 rm -r ~/.cache/pip
4. 最後可以啟用 Overlay Filesystem + ReadOnly Boot Partition 了. 之後要是想裝東西可以直接使用 Docker, 改動會保存在外接硬碟中, 就算重裝系統也可以輕鬆恢復數據, 是目前我找到的最好的方案.
raspi-config
5月26日附: 在插拔 HDMI 线的时候不小心把电源也带出来了,赶紧插上,开机没发现任何问题,一分钟后博客恢复访问,lost+found下没添加任何文件。Overlay filesystem 确实是,高!
要用到 Nginx 的額外功能, 我需要安裝插件合集 nginx-extras
. 但是官方 Nginx 鏡像並不提供插件功能, 而我也不想就為了這麽一個小功能就去用別人自己 Build 的鏡像, 鬼知道裡面有什麼東西.
我了解到 官方 Nginx, 如果沒有特殊指定的話, 是基於 Debian 的. 那麼在 Debian 裡面如果我想要安裝這個插件, 我只需要執行以下命令, 就可以用了
apt-get update && apt-get install -y nginx-extras
經過簡單的搜索, 我發現 Docker 提供 Dockerfile
的方法來構建自己的鏡像. 就是一個小腳本, 有點像 Git Actions 那樣的小腳本, 不過比那個還簡單.
知道了 Dockerfile 怎麼使用之後, 就可以上手了
FROM nginx:latest RUN apt-get update RUN apt-get install -y nginx-extras
docker build -t nginx_extras . docker image ls
因為我用了 Portainer, 我可以直接替換鏡像為我自己構建的 nginx_extras
.
到此為止, Nginx 已經可以用上這些插件了.
簡單的紀錄一下我瞎搞Docker的時候碰到的一個坑:
我現在要配置一個Nginx, 跑在路由器上, 地址是 192.168.10.1
;
我要用 Nginx 反向代理一個網站, 跑在這個局域網裡面, 地址是 192.168.10.10
這其實根本就超簡單, 正常情況下沒有 Docker, 我們就直接編輯 /etc/nginx/conf.d/default.conf, 然後在裡面扔以下配置, 就直接 Ok (緩存啥的都有照顧到, 我就拿這個作為模板)
server {
listen 80;
listen 443 ssl http2;
server_name 127.0.0.1;
ssl_certificate /etc/ssl/fullchain.pem;
ssl_certificate_key /etc/ssl/private.key;
ssl_protocols TLSv1.1 TLSv1.2 TLSv1.3;
ssl_ciphers EECDH+CHACHA20:EECDH+CHACHA20-draft:EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256:EECDH+3DES:RSA+3DES:!MD5;
ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
add_header Strict-Transport-Security "max-age=31536000";
error_page 497 https://$host$request_uri;
location / {
proxy_pass https://justin.education;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header REMOTE-HOST $remote_addr;
add_header X-Cache $upstream_cache_status;
#Set Nginx Cache
proxy_set_header Accept-Encoding "";
sub_filter "http://192.168.10.10" "https://192.168.10.1";
sub_filter "https://192.168.10.10" "https://192.168.10.1";
sub_filter_once off;
proxy_ignore_headers Set-Cookie Cache-Control expires;
proxy_cache_key $host$uri$is_args$args;
proxy_cache_valid 200 304 301 302 10m;
}
}
然後就一直提示我 502 Bad Gateway, 我就 …
愣是浪費我整整一個小時時間來檢查哪裡有問題, 所以說思維定勢真的不可取, 你說他每次用都好好的, 怎麼一到 Docker 上面就出問題?
不過萬幸的是我想起來起看了一眼日誌 (日誌一定得看啊) , 然後發現一直提示訪問 172.17.0.1 報錯…
於是我去谷歌上面搜了一下 鏈接 , 發現 172.17.0.1/
16 是 Docker 自己的一個網段, 是通過 NAT 橋接到 Host 網絡的.
這就… 怪不得. 都不在一個網段裡面, 訪問得到才有鬼
知道就好辦, 直接在 Portainer 裡面從 Bridge 改為 Host 就解決了問題.
早晨我例行的摸了一下鏈接到樹莓派的硬盤,結果發現它不轉了。Nani?
於是我立即嘗試登錄寶塔面板,結果發現卡在登錄頁面。
使用SSH重啓之後根本重連不上,網關提示根本沒給它分配IP,就是說它現在不能聯網。
我把樹莓派強制斷電後插電,可以連上了,但是提示的消息卻讓我比較震驚…
於是我決心把他弄懂。
首先肯定是要確定磁盤佔用是這樣…
$ df -h
Filesystem Size Used Avail Use% Mounted on
tmpfs 782M 60M 723M 8% /run
/dev/mmcblk0p2 117G 117G 0 100% /
tmpfs 3.9G 0 3.9G 0% /dev/shm
tmpfs 5.0M 0 5.0M 0% /run/lock
tmpfs 4.0M 0 4.0M 0% /sys/fs/cgroup
/dev/mmcblk0p1 253M 152M 101M 60% /boot/firmware
/dev/sda1 916G 95G 776G 11% /media/backup
tmpfs 782M 4.0K 782M 1% /run/user/0
是這樣沒錯,然後要定位到主目錄,看看到底那個文件夾出了問題。
$ cd /
$ du -h -x --max-depth=1
74M ./home
2.9G ./usr
8.0K ./.disk
24K ./snap
4.0K ./mnt
4.0K ./srv
114M ./root
72K ./tmp
117M ./boot
16K ./opt
8.0K ./patch
6.1M ./etc
4.0K ./media
4.1G ./www
110G ./var <- 問題根源
16K ./lost+found
117G .
經過一番定位之後,現在可以發現問題的根源在這個文件夾裏:
/var/lib/docker/containers/6c8a****13f4/
進一步定位那個文件出了問題:
$ ll
total 112907424
drwx------ 4 root root 4096 Jan 7 04:41 ./
drwx------ 4 root root 4096 Feb 3 21:06 ../
-rw-r----- 1 root root 115617058816 Feb 18 13:05 6c8a****13f4-json.log
drwx------ 2 root root 4096 Feb 3 16:33 checkpoints/
-rw------- 1 root root 3958 Jan 7 04:41 config.v2.json
-rw-r--r-- 1 root root 1513 Jan 7 04:41 hostconfig.json
-rw-r--r-- 1 root root 13 Feb 5 13:29 hostname
-rw-r--r-- 1 root root 174 Feb 5 13:29 hosts
drwx------ 3 root root 4096 Feb 3 16:33 mounts/
-rw-r--r-- 1 root root 612 Feb 5 13:29 resolv.conf
-rw-r--r-- 1 root root 71 Feb 5 13:29 resolv.conf.hash
恐怖的發現…這個日誌文件竟然佔了這麼多的大小…
看了一下日誌,整個日誌基本全是 P2P文件交換的記錄。
離譜的是這個日誌居然是以毫秒記錄的,有的地方甚至一毫秒幾十行…這個樹莓派是怎麼支撐過來的?
因爲沒有值得注意的東西,我就直接 rm
掉了。瞬間執行,滿足感還是很高的, WinServer不知道刪到猴年馬月去。
(Ext4文件系統刪除文件時並沒有對數據進行操作,我的理解中是將記錄文件信息的索引釋放掉了,在系統的想法裏這片空間又變回可寫的了)
$ df -h
Filesystem Size Used Avail Use% Mounted on
tmpfs 782M 79M 703M 11% /run
/dev/mmcblk0p2 117G 9.3G 103G 9% /
tmpfs 3.9G 0 3.9G 0% /dev/shm
tmpfs 5.0M 0 5.0M 0% /run/lock
tmpfs 4.0M 0 4.0M 0% /sys/fs/cgroup
/dev/mmcblk0p1 253M 152M 101M 60% /boot/firmware
/dev/sda1 916G 95G 776G 11% /media/backup
tmpfs 782M 4.0K 782M 1% /run/user/0
很好,空間佔用回到正常了。
既然知道了是日誌文件的問題,現在就要搞清楚到底那個容器出了問題。
$ docker ps -a
CONTAINER ID IMAGE
84e1a7934eb6 linuxserver/syncthing:latest
6c8a506e5aca linuxserver/resilio-sync:latest
現在就知道哪裡出現問題了。可以看到,resilio-sync 的id對應了那個日誌文件的開頭。
我更改了resilio sync中的設置,分別更改爲
log_size = 0
log_ttl = 0
disk_low_priority = true
希望這樣可以有效果,我會在幾天後再來查看。
实测这样子并没有效果,看起來是Docker鏡像製作時留下來的問題, 直接在容器裡更改配置不起作用.
那這不簡單.
docker pause ResilioSync
rm 6c8a****13f4-json.log
ln -s /dev/null 6c8a****13f4-json.log
$ ll
總計 36K
drwx------ 2 root root 4.0K 1月 1 2038 checkpoints
-rw------- 1 root root 4.9K 5月 5 10:25 config.v2.json
lrwxrwxrwx 1 root root 9 5月 5 10:26 6c8a****13f4-json.log -> /dev/null
-rw-r--r-- 1 root root 2.2K 5月 5 10:25 hostconfig.json
-rw-r--r-- 1 root root 13 5月 4 22:14 hostname
-rw-r--r-- 1 root root 174 5月 4 22:14 hosts
drwx-----x 2 root root 4.0K 1月 1 2038 mounts
-rw-r--r-- 1 root root 61 5月 4 22:14 resolv.conf
-rw-r--r-- 1 root root 71 5月 4 22:14 resolv.conf.hash
docker unpause ResilioSync
问题到此解决
沒解決.
這樣做之後確實一時爽, 但是過了一天我回來看, 發現容器停止運行, 原因是
/mnt/data/docker/containers/6c8a****13f4-json.log/dev/null no file or directory
所以問題到底怎麼解決呢?
經過一番搜索(現在才想起來有谷歌這回事)之後, 我得到了結果, 問題完美解決.
原來是可以通過配置 docker-compose 來限制logsize的, 比如說我要限制 nginx 的 logsize 為5g, 我可以
nginx:
image:
restart: always
logging:
driver: “json-file”
options:
max-size: “5g”
那麼我是用portainer管理docker的, 我可以
問題到此真正完美解決.
我正在配置 Qt wasm環境,
但是 emsdk 不支持 apple m1 issue 769 使用 Homebrew 安裝的 emsdk 一直報錯,
沒找到源碼編譯的 Guide 只好使用 Docker.
環境
MacOS Bigsur M1, nodejs
官網指南: 點擊前往
根據官網的描述, Docker 是使用了 QEMU 來虛擬出 AMD/x86 的環境, 反正能正常工作.
首先需要安裝 Rosetta2, 應該都已經有了
softwareupdate --install-rosetta
然後點擊下載 Docker Desktop RC3, 簡單的安裝後啟動, 會要求獲取 root 權限.
點擊 settings - Docker Engine
, 在頁面中間的框框裡面加入這麼一行, 配置科大鏡像:
"registry-mirrors": [ "https://docker.mirrors.ustc.edu.cn/" ],
至此, Docker 配置完畢了.
emscripten/emsdk
: Docker Hub
以上是兩個所需鏡像, 第二個是可選項. 如果你不是配合 qt 使用的話, 只選第一個就可以了.
但是如果你要配合 qt 使用, 兩個都得裝, 原因會在下文提及.
首先先 拉取 emsdk 的鏡像, 根據 Qt官網 的描述, 我需要的版本是 1.39.8 , 所以我的命令是:
docker pull emscripten/emsdk:1.39.8
沒有特殊要求的話, 後面的 :1.39.8
可以改成 :latest
, 或者根本不加, 直接拉取最新版本.
測試一下鏡像:
cd /tmp # create helloworld.cpp cat << EOF > helloworld.cpp #include <iostream> int main() { std::cout << "Hello World!" << std::endl; return 0; } EOF # compile with docker image docker run \ --rm \ -v $(pwd):$(pwd) \ -u $(id -u):$(id -g) \ emscripten/emsdk \ emcc helloworld.cpp -o helloworld.js # execute on host machine node helloworld.js
如果看到 輸出 Hello World!
的話, 配置成功了.
每次使用打這麼一大串肯定不現實, 一般的思路是寫一個別名:
# vim ~/.zshrc alias emcc='docker run \ --rm \ -v $(pwd):$(pwd) \ -u $(id -u):$(id -g) \ emscripten/emsdk \ emcc' alias em++='docker run \ --rm \ -v $(pwd):$(pwd) \ -u $(id -u):$(id -g) \ emscripten/emsdk \ em++' # 應用配置 source ~/.zshrc
這樣手敲就沒問題了, 但是用諸如 vscode 之類的工具配置環境會比較煩, 更加穩妥的方式是將其寫進 bash 腳本裡面:
echo '#!/bin/bash /usr/local/bin/docker run \ --rm \ -v $(pwd):$(pwd) \ -u $(id -u):$(id -g) \ emscripten/emsdk \ emcc $*' > /usr/local/bin/emcc echo '#!/bin/bash /usr/local/bin/docker run \ --rm \ -v $(pwd):$(pwd) \ -u $(id -u):$(id -g) \ emscripten/emsdk \ em++ $*' > /usr/local/bin/em++ sudo chmod +x /usr/local/bin/emcc sudo chmod +x /usr/local/bin/em++
至此, emsdk 的安裝已經基本完成.