Cygwin 建置
Cygwin 安裝
Cygwin 是在 Windows 中一個 POSIX 系統 (例如 Linux),將原本 POSIX 系統中的軟體重新編譯移植至 Windows。
至 Cygwin Installation 下載 setup-x86_64.exe,將 setup-x86_64.exe 放置於 c:\apps。
由 Cygwin Mirror Sites 得知下載套件的網址 (要複製連結或點選才正確),如 Taiwan: ftp.ntu.edu.tw
實際網址為 https://ftp.ntu.edu.tw/pub/cygwin/
。
列出 setup-x86_64 的說明,可執行下列:
c:\apps\setup-x86_64 --help
setup-x86_64.exe 參數簡要說明
c:\apps\setup-x86_64 -D -B -l c:\apps\cygwin.pkg -s https://ftp.ntu.edu.tw/pub/cygwin/
-
第 1 頁為版本說明。
-
第 2 頁應該為 Download Without Installing (只下載不安裝)。
-
第 3 頁 Local Package Directory 應該是 c:\apps\cygwin.pkg (已預設好)。
-
第 4 頁 Use System Proxy Settings (預設值,不用改)
-
第 5 頁 Choose A Download Site 應該是 https://ftp.ntu.edu.tw (已預設好)。
本步驟僅測試,並不需實際下載,確認參數合乎預期後,可離開安裝程式。
安裝或下載後,本機套件儲存目錄中會有 下載網址
的資料夾,如果變更 下載網址
會再建立一個,這表示;如果要重複使用,那麼 下載網址
不應變更。
再來,指定安裝目錄 (-R
) 安裝至 c:\apps\cygwin
。
c:\apps\setup-x86_64 -B -R c:\apps\cygwin -l c:\apps\cygwin.pkg -s https://ftp.ntu.edu.tw/pub/cygwin/
-
第 2 頁應該為 Install from Internet (下載的檔案會保留至本機套件儲存目錄)。
註:setup-x86_64.exe 選項 -L
由本機套件目錄安裝,如果沒有安裝過 Cygwin,那麼本機套件並不完整,安裝的 Cygwin 無法執行,第一次安裝不要採用該方式來安裝。
安裝或更新時,可採用無人值守安裝模式 (-q
) 及指定安裝套件 (-P
) 一併安裝 openssh,ping,wget,curl,zip,unzip,nano。
註:scp ssh 的套件是 openssh。
c:\apps\setup-x86_64 -q -B -R c:\apps\cygwin -l c:\apps\cygwin.pkg -s https://ftp.ntu.edu.tw/pub/cygwin/ -P openssh,ping,wget,curl,zip,unzip,nano
{ "name" : "Cygwin", "commandline" : "c:/apps/cygwin/bin/bash --login -i", "icon" : "c:/apps/cygwin/Cygwin.ico", "hidden": false },
Cygwin 版本
Cygwin 的版本可由 cygcheck -c cygwin
或 cygcheck -V
得知套件的版本,uname -r
得知 dll 的版本,「套件」跟「dll」的版本應該一致。
執行下列得知 cygwin (套件) 的版本:
cygcheck -c cygwin
Cygwin Package Information
Package Version Status
cygwin 3.4.5-1 OK
執行下列得知 cygwin (套件) 的版本:
cygcheck -V
cygcheck (cygwin) 3.4.5
執行 uname 得知 (dll) 版本:
uname -r
3.4.5-1.x86_64
註:C:\apps\cygwin\bin\cygwin1.dll (/bin/cygwin1.dll) 的版號為 3.4.5
cygwin 是安裝測試版:
cygcheck -c cygwin
Cygwin Package Information
Package Version Status
cygwin 3.5.0-0.140.gbf915420042e OK (1)
執行下列得知 cygwin (套件) 的版本:
cygcheck -V
cygcheck (cygwin) 3.5.0
測試版執行 uname 得知 (dll) 版本:
uname -r
3.5.0-0.140.gbf915420042e.x86_64
註:C:\apps\cygwin\bin\cygwin1.dll 的版號為 3.5.0
1 | 當尾碼有長編號時,並非表示該套件一定是測試版,執行 setup-x86_64 至 Select Packages 頁面,在 New 欄位下拉「向下按鈕」,在列表中會顯示 版號(Test) ,如 cygwin 的 3.5.0-0.140.gbf915420042e(Test) 即為測試版。 |
當更新 cygwin 核心套件時,應關閉 cygwin CLI,如果沒有可能會發生「套件」跟「dll」不一致。
- 「套件」跟「dll」不一致時解決方式
-
執行 setup-x86_64 至
Select Packages
頁面,在 Search (搜尋) 輸入cygwin
,在找出的項目cygwin
及cygwin-devel
按下「向下按鈕」選取reinstall
,按下 下一步 前要關閉 cygwin CLI。
Cygwin 環境說明
在 Cygwin 的根目錄 (/
) 為安裝 Cygwin 的路徑如 (c:\apps\cygwin
),在 Cygwin 中的 /home
即為 C:\apps\cygwin\home
。
而 ~
表示使用者主目錄,如使用者名稱為 user
, ~
即為 /home/user
。
在 Cygwin 中的 /usr/bin
比較特殊,Windows 的路徑是在 C:\apps\cygwin\bin
。
Cygwin 讀取外部目錄 (指 Cygwin 安裝路徑之外),可直接採用 Windows 路徑其前後加上單引號 ('
) 或雙引號 ("
), 或者以 cygpath 轉換成 cygdrive 格式。不過,大部份的命令並不支援 cygdrive 格式,當然也有部份命令不支援雙引號只能採用 cygdrive 格式。
比較好的方式,先切換至工作目錄 (不在安裝路徑中,如 D:\MyProject
),在工作目錄中以相對路徑存取子資料夾,建立的指令檔也以相對路徑來設定輸入或輸出。
cygpath 簡要說明 (cygpath --help
)
以雙引號切換路徑:
cd "C:\Windows"
可以看到命令提示列為 Unix 路徑
user@MyPC /cygdrive/c/Windows
目前路徑轉成 Windows 路徑:
cygpath -aw .
C:\Windows
主目錄轉成 Windows 路徑:
cygpath -aw ~
C:\apps\cygwin\home\user
取得 Unix 絕對路徑:
註:-u 列出 Unix 路徑為預設值不需要指定。另外執行 cygpath 時;一般情況不會為「相對」,雖然並不需要 -a 的選項,但建議加入。
cygpath -a "c:\apps\setup-x86_64.exe"
/cygdrive/c/apps/setup-x86_64.exe
以 cygstart 執行 Windows 檔案總管開啟目前的資料夾: cygstart . 啟動與 .txt 關聯的編輯器(例如記事本): cygstart my.txt 註:檔案在目前的資料夾。
貼上 Cygwin 會顯示成反白 (Highlighted),非常不習慣改掉它。
查詢設定值:
bind -V | grep enable-bracketed-paste
enable-bracketed-paste is set to `on'
暫時取消:
bind 'set enable-bracketed-paste off'
echo "set enable-bracketed-paste off" >> ~/.inputrc
再來重啟「終端機」。
修改使用者
mkpasswd --local > /etc/passwd
開啟 c:\apps\cygwin\etc\passwd 或 nano /etc/passwd
nano 操作簡易說明
^O
儲存,^X
退出,^W
搜尋
註:^
為按下 Ctrl 鍵。
修改前
winuser:*:197610:197121:U-W10T#winuser#,S-1-5-21-2503564773-1016231635-2146039180-1002:/home/winuser:/bin/bash
修改後
user:*:197610:197121:U-W10T#winuser#,S-1-5-21-2503564773-1016231635-2146039180-1002:/home/user:/bin/bash
如把目前 Windows 的使用者 winuser 改為 user。
有兩個,一個為帳號 (在前面的位置),一個為使用者主目錄 (在後面的位置),中間的 winuser 不要動。
存檔後,將主目錄 c:\apps\cygwin\home\winuser 改名 c:\apps\cygwin\home\user。
可採用檔案總管或在 cygwin 內執行下列:
mv /home/$(whoami) /home/user
再來重啟「終端機」。
改為英文介面及修改命令提示列。
~/.bashrc
開啟 C:\apps\cygwin\home\user\.bashrc 或 nano ~/.bashrc
~/.bashrc
# 本行為備註。前置 # 表示為備註。
export TIME_STYLE=long-iso
export LANG="en_US.UTF-8" (1)
export PS1='\n\[\e[0;32m\]cygwin2 \[\e[0;33m\]\w\[\e[0m\]\n\$ '(2)
1 | 改為英文介面,原始為 zh_TW.UTF-8 |
2 | 「命令提示列」預設為 使用者名稱@電腦名稱 ,如果有多個 Cygwin 可修改「命令提示列」,本例為 cygwin2 。 |
套用 bash 環境及配置: source ~/.bashrc 檢查一下設定是否正確: echo $TIME_STYLE echo $LANG
Cygwin 的 PATH
預設會納入 Windows 的 Path
環境變數。在執行命令時,可能執行 Windows 的執行檔,造成混淆,建議將 PATH
限制在 Cygwin 的環境中。
在 Cygwin 檢查 PATH:
echo $PATH
/usr/local/bin:/usr/bin:/cygdrive/c/WINDOWS/system32: ...
PATH
是以冒號 (:
) 來區分,主要路徑為前二個 /usr/local/bin
、/usr/bin
。
~/.bashrc
重新設定 PATH
及加入其他路徑 (如 ~/bin
)export PATH="/usr/local/bin:/usr/bin:~/bin"
export
同等於 Windows 中的 set
,如將變數 myUp
設定為 Windwos 環境變數 %USERPROFILE%
,在 Cygwin 中以 $USERPROFILE
取得。
取得 USERPROFILE 的 Unix 路徑: cygpath $USERPROFILE /cygdrive/c/Users/winuser 設定 myUp 變數: export myUp=/cygdrive/c/Users/winuser 切換至 C:\Users\winuser: cd $myUp
export myUp=$(cygpath $USERPROFILE) cd $myUp
myPath=$(cygpath $USERPROFILE) cd $myPath
進入一個子進程: bash 查詢 myUp 變數: echo $myUp 回傳: /cygdrive/c/Users/winuser 查詢 myPath 變數: echo $myPath 並沒有回傳值,因為 myPath 為臨時變數。 PATH 要以 export 來設定,因為子進程共享環境變數。
以 alias 建立指令別名
建立 cup 別名將目前路徑切換至 %USERPROFILE%: alias cup="cd $(cygpath $USERPROFILE)" 執行 cup: cup 可以看到命令提示列的路徑已切換 user@MyPC /cygdrive/c/Users/winuser
Cygwin bashrc
cat > ~/.bashrc << "EOF"
export TIME_STYLE=long-iso
export LANG="en_US.UTF-8"
export PS1='\n\[\e[0;32m\]'$(basename "$(cygpath -aw /)")' \[\e[0;33m\]\w\[\e[0m\]\n\$'
export PATH="bin:~/bin:/usr/local/bin:/usr/bin:~/node_modules/.bin:/usr/local/npm:/cygdrive/c/apps/nodejs:/cygdrive/c/WINDOWS/system32"
export NODE_PATH="$(cygpath -aw ~/node_modules);$(cygpath -aw /usr/local/npm/node_modules)"
alias code="'$(cygpath "$USERPROFILE\AppData\Local\Programs\Microsoft VS Code\bin\code.cmd")'"(1)
EOF
# 套用 bash 環境及配置
source ~/.bashrc
1 | 加入 VSCode 的別名。 |
註:上述的 .bashrc
雖然會依據 Cygwin 安裝路徑自動設定 NODE_PATH 的路徑,但 npm 的 prefix 並未變更,若要變更執行下列。
設定 prefix 為 /usr/local/npm (由 cygpath 轉成 Windows 路徑): npm config set prefix "$(cygpath -aw /usr/local/npm)" 檢查結果: npm config get prefix
Cygwin ACL
執行 setup-x86_64.exe
以參數 -B
(不以系統管理員身份執行) 安裝 Cygwin。
先設定暫時 PATH:
PATH=$PATH:/cygdrive/c/Windows/System32
列出 Cygwin 根資料夾權限清單:
icacls.exe $(cygpath / -aw)
%USERDOMAIN%\%USERNAME%:(F) %USERDOMAIN%\None:(RX) Everyone:(RX) CREATOR OWNER:(OI)(CI)(IO)(F) CREATOR GROUP:(OI)(CI)(IO)(RX) Everyone:(OI)(CI)(IO)(RX)
剛好有三組 ACE (Access control entry 存取控制項目),上方為檔案或資料夾權限,下方為資料夾繼承權限。
檔案或資料夾權限,F:完整存取權,RX:讀取和執行存取權。
getfacl / # file: / # owner: $USERNAME # group: None user::rwx group::r-x other::r-x default:user::rwx default:group::r-x default:other::r-x
getfacl | icacls |
---|---|
|
|
|
|
|
|
觀察 Cygwin 建立根資料夾之外檔案時 ACL 的情況。
C:\acl-test
並觀察權限清單mkdir c:\acl-test icacls.exe C:\acl-test BUILTIN\Administrators:(I)(OI)(CI)(F) NT AUTHORITY\SYSTEM:(I)(OI)(CI)(F) BUILTIN\Users:(I)(OI)(CI)(RX) NT AUTHORITY\Authenticated Users:(I)(M) NT AUTHORITY\Authenticated Users:(I)(OI)(CI)(IO)(M)
該 C:\acl-test
資料夾,Cygwin 的 ACL 跟 Windows 沒有對應,缺少了 group
(%USERDOMAIN%\None
),在該資料夾建立檔案則 ACL 會出錯 (註:寫入已建立的檔案並不會錯誤)。
C:\acl-test\acl-file
檔案:cd "C:\acl-test"
touch acl-file (1)
1 | 該檔案為新檔,如果已存在應先刪除。 |
acl-file
權限清單,已出錯:icacls.exe acl-file
NULL SID:(DENY)(Rc,S,WEA,X,DC)
%USERDOMAIN%\%USERNAME%:(R,W,D,WDAC,WO) (1)
%USERDOMAIN%\None:(DENY)(S,X)
NT AUTHORITY\Authenticated Users:(DENY)(S,X)
NT AUTHORITY\SYSTEM:(DENY)(S,X)
BUILTIN\Administrators:(DENY)(S,X)
BUILTIN\Users:(DENY)(S,X)
%USERDOMAIN%\None:(RX)
NT AUTHORITY\Authenticated Users:(RX,W)
NT AUTHORITY\SYSTEM:(RX,W)
BUILTIN\Administrators:(RX,W)
BUILTIN\Users:(RX)
Everyone:(R)
1 | 權限清單雖然不正確,但擁有者還是有完整的存取權。
R - 唯讀存取權 W - 唯寫存取權 D - 刪除存取權 WO - 寫入擁有者 |
acl-file
的 ACL,已出錯:icacls.exe acl-file /verify
acl-file: Ace 項目的順序不標準。
切換至使用主目錄後,重建檔案 (註:沒有重建時 ACL 並不會變更): cd ~ rm "C:\acl-test\acl-file" touch "C:\acl-test\acl-file" 觀察權限清單: icacls.exe "C:\acl-test\acl-file" BUILTIN\Administrators:(I)(F) NT AUTHORITY\SYSTEM:(I)(F) BUILTIN\Users:(I)(RX) NT AUTHORITY\Authenticated Users:(I)(M) 檢查檔案 ACL 是否正確: icacls.exe "C:\acl-test\acl-file" /verify 已處理的檔案: C:\acl-test\acl-file (無錯誤) 以 getfacl 列出檔案 ACL: getfacl "C:\acl-test\acl-file" getfacl: C:\acl-test\acl-file: Not supported (不支援)
將 noacl
加入 /etc/fstab
,解決 Cygwin 在根資料夾之外建立檔案造成 ACL 錯誤。
不應讓 Cygwin 造成其他資料夾的 ACL 錯誤,剛安裝 Cygwin 就應該加入 noacl
。
noacl
加入 /etc/fstab
cat << EOF > /etc/fstab
none /cygdrive cygdrive binary,noacl,posix=0,user 0 0
EOF
cat /proc/mounts
如下:先檢查原狀態: cat /proc/mounts C:/apps/cygwin/bin /usr/bin ntfs binary,auto 1 1 C:/apps/cygwin/lib /usr/lib ntfs binary,auto 1 1 C:/apps/cygwin / ntfs binary,auto 1 1 C: /cygdrive/c ntfs binary,posix=0,user,noumount,auto 1 1
檢查重啟後的狀態:
cat /proc/mounts
C:/apps/cygwin/bin /usr/bin ntfs binary,auto 1 1
C:/apps/cygwin/lib /usr/lib ntfs binary,auto 1 1
C:/apps/cygwin / ntfs binary,auto 1 1
C: /cygdrive/c ntfs binary,noacl,posix=0,user,noumount,auto 1 1
cd "C:\acl-test"
rm acl-file
touch acl-file
icacls.exe acl-file (1)
icacls.exe acl-file /verify
getfacl acl-file (2)
1 | 跟資料夾權限一致 (Windows 權限繼承)
BUILTIN\Administrators:(I)(F) NT AUTHORITY\SYSTEM:(I)(F) BUILTIN\Users:(I)(RX) NT AUTHORITY\Authenticated Users:(I)(M) |
2 | getfacl: acl-file: Not supported ,「不支援」才是正確的。 |
cat << EOF > /etc/fstab
none /cygdrive cygdrive binary,posix=0,user 0 0
EOF
將 Cygwin 根資料夾 (以 Windows) 複製至另一個資料夾 (c:\apps\cygwin-c
)
觀察權限清單: icacls.exe "C:\apps\cygwin-c" BUILTIN\Administrators:(I)(OI)(CI)(F) NT AUTHORITY\SYSTEM:(I)(OI)(CI)(F) BUILTIN\Users:(I)(OI)(CI)(RX) NT AUTHORITY\Authenticated Users:(I)(M) NT AUTHORITY\Authenticated Users:(I)(OI)(CI)(IO)(M) 檢查 ACL 是否正確: icacls.exe "C:\apps\cygwin-c" /verify /T /Q 已順利處理 0 個檔案; 0 個檔案處理失敗 (剛開始應該無錯誤)
進入 cygwin-c
建立根資料夾內的檔案時,Cygwin ACL 跟 Windows 沒有對應;已知會出錯。
建立檔案: cd ~ touch acl-file 觀察權限清單: /cygdrive/c/Windows/System32/icacls.exe acl-file NULL SID:(DENY)(Rc,S,WEA,X,DC) %USERDOMAIN%\%USERNAME%:(R,W,D,WDAC,WO) %USERDOMAIN%\None:(DENY)(S,X) NT AUTHORITY\Authenticated Users:(DENY)(S,X) NT AUTHORITY\SYSTEM:(DENY)(S,X) BUILTIN\Administrators:(DENY)(S,X) BUILTIN\Users:(DENY)(S,X) %USERDOMAIN%\None:(RX) NT AUTHORITY\Authenticated Users:(RX,W) NT AUTHORITY\SYSTEM:(RX,W) BUILTIN\Administrators:(RX,W) BUILTIN\Users:(RX) Everyone:(R) 檢查 ACL 是否正確: /cygdrive/c/Windows/System32/icacls.exe acl-file /verify acl-file: Ace 項目的順序不標準。
修正 ACL
cygwin-c
在持續使用時,ACL 錯誤會一直增加。
若需要修正 ACL 錯誤,可執行下列修正,將 Windows 權限配合 Cygwin 的 Owner、Group、Others,並移除其他權限。
/cygdrive/c/Windows/System32/icacls.exe $(cygpath / -aw) \
/grant \
"$USERDOMAIN\\$USERNAME:F" \
"*S-1-3-1:RX" \(1)
"Everyone:RX" \
"CREATOR OWNER:(OI)(CI)(IO)F" \
"CREATOR GROUP:(OI)(CI)(IO)RX" \
"Everyone:(OI)(CI)(IO)RX" \
/remove \
"NT AUTHORITY\\Authenticated Users" \
"NT AUTHORITY\\SYSTEM" \
"BUILTIN\\Administrators" \
"BUILTIN\\Users" \
"NULL SID" \
/inheritance:r /T /C /Q (2)
1 | S-1-3-1 為 Creator Group ID 即為 $USERDOMAIN\None ,S-1-3-1 參閱: Security identifiers | Microsoft Learn 。 |
2 | inheritance:r :移除所有繼承的 ACE,/T :目錄下所有檔案及資料夾,/C :發生錯誤時繼續執行 (仍會顯示錯誤訊息),/Q :(安靜執行) 不顯示成功訊息。 |
檢查 Cygwin 根資料夾內所有檔案 ACL 是否正確: /cygdrive/c/Windows/System32/icacls.exe $(cygpath / -aw) /verify /T /Q
Ruby
安裝 ruby 可採用 setup-x86_64
手動安裝或建立 cygpkg 按下列安裝
cygpkg install ruby
gem 安裝路徑
gem env
如下(省略跟安裝路徑無關的訊息):RubyGems Environment:
- INSTALLATION DIRECTORY: /usr/share/gems
- USER INSTALLATION DIRECTORY: /home/user/.gem/ruby/2.6.0
- GEM PATHS:
- /usr/share/gems
- /home/user/.gem/ruby/2.6.0
- /usr/local/share/gems
- GEM CONFIGURATION:
- "gem" => "--user-install --bindir /home/user/bin"
-
一個是安裝目錄
INSTALLATION DIRECTORY: /usr/share/gems
。
註:實際上還再附加 gems,如/usr/share/gems/gems
。 -
另一個是使用者安裝目錄
USER INSTALLATION DIRECTORY: /home/user/.gem/ruby/2.6.0
。
註:跟上述的註解一樣,要附加 gems。
gem install
會安裝至「使用者安裝目錄」,也會在 /home/user/bin
建立指令檔。~/bin
應納入 PATH。
採用 bundle
將安裝至「安裝目錄」,並不會在 ~/bin
建立指令檔。
更新套件時可能會安裝在 /usr/share/gems
。
gem 常用命令
gem search <套件REGEXP> [選項] 「套件REGEXP」表示找出前置合乎「套件名稱」的所有套件,除非加入 -e 選項 (全吻合)。 註:套件名稱不可含版號。 search 有那些可用選項: gem search -h -a, --all 顯示 gem 所有版本 -e, --exact 套件名稱全吻合 --prerelease 顯示預先發行版本 (註:可簡化成 --pre)
gem list
gem list <套件REGEXP> -d 如詳細資料中顯示 Installed at: /home/user/.gem/ruby/2.6.0 實際安裝的路徑是在 /home/user/.gem/ruby/2.6.0/gems/套件含版號,如果有更新,會顯示多個版本。
gem which <套件> 一般情況,套件的指令檔會在套件的安裝路徑之中,套件的「資料」可能在指令檔的上層。多個版本時應採用 which 來得知目前是用那一個版本。
安裝 gem-path 套件:
gem install gem-path
執行 gem-path 得知套件安裝路徑:
gem path <套件>
Node.js
Cygwin 的套件中並沒有 NodeJS,但 Windows 平台的 NodeJS 可在 Cygwin 內使用。
安裝 NodeJS 由 Download | Node.js 下載 Windows Binary (.zip) 64 bits 解壓至 c:\apps\nodejs
。
取得 Unix 路徑: cygpath "c:\apps\nodejs" /cygdrive/c/apps/nodejs 檢查 nodejs 下載的版本: /cygdrive/c/apps/nodejs/npm -v
-global
) 模組時,先瞭解 npm 的路徑關係。先設定暫時的 PATH 變數
PATH="/usr/local/bin:/usr/bin:/cygdrive/c/apps/nodejs"
顯示 prefix 的預設值:
npm config get prefix
C:\apps\nodejs
顯示執行檔 (bin) 路徑:
npm bin -global
C:\apps\nodejs
顯示模組路徑:
npm root -g
C:\apps\nodejs\node_modules
由上述可知,在 Cygwin 中 npm 執行檔 (bin) 路徑跟 {prefix}
相同,而模組路徑是在 {prefix}/node_modules
,這兩者跟 npm-bin | npm Docs 上的說明不同。
Cygwin | npm-bin | npm Docs | |
---|---|---|
packages |
|
|
bin |
|
|
設定 prefix
路徑為 /usr/local/npm
,由於 NodeJS 是 Windows 平台,需要以 Windows 的路徑來設定 prefix
及 NODE_PATH
。
在 Cygwin 一定要設定 NODE_PATH
,命令 node
才能找到全局模組,另外;執行 node
的命令是子進程,要以 export
來設定 NODE_PATH
。
設定 prefix 為 /usr/local/npm (由 cygpath 轉成 Windows 路徑):
npm config set prefix "$(cygpath -aw /usr/local/npm)"
檢查結果:
npm config get prefix
C:\apps\cygwin\usr\local\npm
顯示模組路徑:
npm root -g
C:\apps\cygwin\usr\local\npm\node_modules
顯示執行檔 (bin) 路徑:
npm bin -g
C:\apps\cygwin\usr\local\npm
npm ERR! bin (not in PATH env variable)
提示執行檔沒有納入 PATH 變數。
列出 .npmrc 的內容:
cat ~/.npmrc
prefix=C:\apps\cygwin\usr\local\npm
在指定的路徑 (locally 本地) 中安裝模組時,如使用者主目錄 (~),則會在該目錄中建立兩個檔案 package.json
及 package-lock.json
(註:全局沒有這些檔案),模組儲存在 ~/node_modules
,執行檔路徑為 ~/node_modules/.bin
。npm root
及 npm bin
剛好就是主目錄路徑,但那不重要,主要是以 NODE_PATH
及 PATH
為準,如果只是引用函數庫並不需要將 ~/node_modules/.bin
納入 PATH
。
在「本地」路徑安裝模組之前,先在本地執行初始化 npm init -y
,如果沒有初始化;則 npm 會自動找出上層的模組設定檔 (package.json
),並將模組安裝在上層。註:主目錄 ~
上層並不會安裝 npm 模組,可不需要初始化。
npm 維護模組時如 install
、uninstall
、update
、list
,區分「本地」及「全局」,本地安裝 (install) 時需將目前路徑切換至「本地」,本地安裝則以本地移除 (uninstall),本地移除時並不會移除全局。
node 在執行 .js
時,會先找出該檔案路徑或 (所有的) 上層路徑是否有 node_modules
子目錄,如果有則會載入 node_modules
內的模組 (不需要設定 NODE_PATH
)。
當 .js
檔案在不同的路徑中則要設定 NODE_PATH
(該設定值有順序,本地路徑要在全局之前)。
何種情況,需要在本地路徑中安裝模組?
如安裝舊版的模組時,最好不要以全局安裝,全局模組應為最新的模組,舊版的模組應該安裝在本地,避免全局模組在安裝或更新時,自動更新。
~/.bashrc
如下新增(或修改)export PATH="/usr/local/bin:/usr/bin:~/node_modules/.bin:/usr/local/npm:/cygdrive/c/apps/nodejs
export NODE_PATH="C:\apps\cygwin\home\user\node_modules;C:\apps\cygwin\usr\local\npm\node_modules"
|
安裝模組。 |
|
移除模組。 |
|
顯示已安裝的模組。 |
|
更新模組及相依模組至最新版本。 |
|
檢查可安裝模組的 (最新) 版本。 |
|
檢查可安裝模組的所有版本。 |
|
查詢可安裝的模組的資訊,如版本、相依模組等 (JSON)。 |
|
搜尋可安裝模組。 |
|
列出組態。 |
|
列出所有組態。 |
相關網頁:
npm Docs
cygpkg 套件安裝移除及更新
在 cygwin 主控台 (CLI) 中執行套件安裝移除及更新,交由 setup-x86_64.exe 來維護, 下載套件時於指令碼指定下載網站及指定儲存於本機 (共用) 套件目錄。
bind "set disable-completion on"
bash -c 'cat > /usr/local/bin/cygpkg' << "EOF"
#!/bin/bash
usage="Usage: ${0##*/} operation [package(s)]
OPERATIONS:
i, install Install package(s).
r, remove Remove package(s).
u, update Update package(s), display the installer, and update manually.
f, fix Update packages to the current release version."
ExecuteFile='c:\apps\setup-x86_64.exe'(1)
params='-l "c:\apps\cygwin.pkg" -s https://ftp.ntu.edu.tw/pub/cygwin/'(2)
UpdatePkgs=0
case "$1" in
i|install)
params="${params} -q -P";
shift;
pkgs=$@;;
r|remove)
params="${params} -q -x";
shift;
pkgs=$@;;
u|update)
UpdatePkgs=1;
params="${params} -M";
shift;
pkgs=$@;;
f|fix)
UpdatePkgs=1;
params="${params} -f -M";
pkgs='';;
-h|--h*) echo "$usage"; exit 0;;
-*|--*) echo "unknown option: $1" >&2; exit 1;;
*) echo "$usage"; exit 0;;
esac
pkgs=${pkgs//,/ }
pkgs="$(echo $pkgs)"
pkgs=${pkgs// /,}
if [ $UpdatePkgs -ge 1 ]; then
if [[ -n "$pkgs" ]]; then
pkgs="-P ${pkgs}"
fi
elif [[ -z "$pkgs" ]]; then
echo "$usage"
exit 1
fi
if [ -f /var/log/setup.log ]; then
logsize=$(stat -c%s /var/log/setup.log)
let MaxSize=10*1024*1024
if [ $logsize -gt $MaxSize ]; then
echo "The /var/log/setup.log ("$(numfmt --to=iec $logsize)") is larger than 10M, it seems abnormal,"
read -p "Do you want to delete it? (Y/N): " yn
if [ "${yn}" != "Y" ] && [ "${yn}" != "y" ]; then
exit 1
fi
set -e
rm /var/log/setup.log
touch /var/log/setup.log
set +e
fi
fi
show_size() {
if [ -f /var/log/setup.log ]; then
logsize=$(stat -c%s /var/log/setup.log)
else
logsize=0
fi
echo -e "\nThe size of /var/log/setup.log is "$(numfmt --to=iec $logsize)"."
exit
}
if [[ -n "$pkgs" ]]; then
cmdline="'$(cygpath -a "$ExecuteFile")' -B -d -n -N --no-write-registry -R \"$(cygpath -aw /)\" ${params} ${pkgs}"
echo $cmdline
trap show_size INT
echo -e "\033[1;33mNotice! When specifying a package, do not select Cygwin core in the installer to update.\033[0m"
eval $cmdline
show_size
else
cmdline="cygstart CMD '/K (\"$ExecuteFile\" -B -d -n -N --no-write-registry -R \""$(cygpath / -aw)"\" ${params})'"
echo $cmdline
echo -e "\033[1;33mWhen updating the Cygwin core, you must exit the Cygwin CLI.\033[0m"
eval $cmdline
fi
EOF
bind "set disable-completion off"
chmod +x /usr/local/bin/cygpkg
1 | setup-x86_64.exe 的全路徑。 |
2 | 本機套件儲存目錄及指定下載網站,注意 -l "c:\apps\cygwin.pkg" 要雙引號。 |
安裝套件:
cygpkg install zip,unzip,nano
或以空白區分套件:
cygpkg install zip unzip nano
移除套件:
cygpkg remove zip,unzip,nano
顯示套件更新(未指定套件,以 cmd 進程執行):
cygpkg update
套件更新 (或安裝指定版本):
cygpkg update gcc-g++=7.4.0-1
setup-x86_64.exe
) 更新 Cygwin core (核心),更新時會出現下列訊息:io_stream_cygfile: fopen(/usr/bin/cygwin1.dll) failed 13 Permission denied Failed to open cygfile:///usr/bin/cygwin1.dll for writing. running: c:\apps\cygwin\bin\kill.exe -TERM -W 10124 [處理結束,代碼為 4294967295 (0xffffffff)]
因為更新 Cygwin core 會終止 Cygwin CLI 進程,為正常現像。但有時不會執行「終止」,則可能會造成 /bin/cygwin1.dll
的版本不一致,在更新核心時,應退出 Cygwin CLI。若版本已不一致,解決方式可參閱 Cygwin 版本。
有指定套件時,如 cygpkg u nano
不應選取 Cygwin core,在指定套件的情況下 cygpkg 並未以 cmd 進程來執行,執行更新後 Cygwin 將會崩溃。
bash: /usr/bin/locale: No such file or directory bash: /usr/bin/tzset: No such file or directory
cygpkg f
JavaScript 套件
JSHint
JSHint 檢查 JavaScript 錯誤,如以建議 === 或 !== 以避免轉型、變數沒有以 var 宣告、陳述式結尾沒有加分號。 剛學 JavaScript,範例以瀏覽器測試是正確,可是採用 JSHint 檢查後才發覺函數不存在 …。
把 JavaScript 貼上 JSHint 可即時檢查出錯誤。
npm install -global jshint
cd $docs
jshint $InputFile
如出現 Something is available in ES6,表示 JavaScript 使用了 ECMAScript 6,那它會不會太新?
ECMAScript - 維基百科,自由的百科全書
jshint -v
# jshint v2.12.0 (1)
1 | JSHint Blog 只會在某個版本說明, New Release: 2.10.0 : support for the three most recent editions of JavaScript: ES7, ES8, and ES9. |
那如何設定讓 JSHint 檢查的 ES 版本;可參考 JSHint Documentation ,實測順序如下。 另外選項可參考 JSHint Options Reference 。
-
.js
加入/* jshint esversion:5, maxdepth:1 */
-
--config
參數指定設定檔 -
.jshintrc
設定檔 (跟 .js 相同的目錄),可按照 jshint/.jshintrc at master · jshint/jshint · GitHub 來設定。
'jQuery' is not defined.
{ // https://github.com/jshint/jshint/blob/master/examples/.jshintrc ... "yui": false, // Yahoo User Interface // Custom Globals "globals": { "jQuery": true // 加入 jQuery } // additional predefined global variables }
陳述式結尾沒有加分號時採用下列自動修正
cd $docs
cat > bin/fixJsFile << "EOF"
#!/bin/sh
for i in `jshint $1 | grep -i "Missing semicolon" \
| sed -e 's/\([^0-9]*\)\([0-9]*\)\(.*$\)/\2/'`;
do
echo 修復檔案:$1 行號: $i
sed -i $1 -e $i's/\(\s*\)$/;/'
wait
done
EOF
fixJsFile $InputOutputFile
terser
GitHub - terser/terser: JavaScript parser, mangler and compressor toolkit for ES6+
JavaScript 壓縮,程式碼縮小化 (變數名稱縮減、去掉註解、空白字元、換行字元 …),去掉 console.log …
npm install -global terser
terser --version
# terser 5.3.4
# 測試,結果顯示主控台
terser $InputFile -c drop_console,passes=2 -m (1)
1 | 參考官方網頁:-c drop_console 去掉 console.log,passes=2 執行 2 次壓縮,-m 變數名稱縮減。 |