1. 程式人生 > >Docker中執行Shell出現亂碼

Docker中執行Shell出現亂碼

腳本 exe 因此 thead gin 並且執行 手動 命令 table

問題描述

最近遇到一個問題:
執行命令 docker exec f4af9b sh -c ‘bash /tmp/build.sh‘ 命令在docker中執行shell,會出現中文亂碼的問題。但是在docker容器中單獨執行shell腳本卻沒有出現亂碼。查看環境變量存在LANG=en_US.UTF-8,因此從原理上來說是不應該出現亂碼的。

但是既然出現了亂碼,那麽LANG=en_US.UTF-8應該就沒有讀取到,於是在 build.sh中運行env命令,發現通過docker exec f4af9b sh -c ‘bash /tmp/build.sh‘方式沒有LANG=en_US.UTF-8環境變量,那麽原因是什麽?

原因定位

原因如下:
docker exec f4af9b sh -c ‘bash /tmp/build.sh‘ 對於docker 容器來說是非登錄和非交互式shell,這樣就不會讀取某些配置文件,導致LANG=en_US.UTF-8沒有加載成功。

Linux Shell

下面介紹一下Linux交互式和非交互式shell、登錄和非登錄shell之間的區別。

  • 交互式shell(interactive shell)和非交互式shell(non-interactive shell)
    • 交互式的shell會有一個輸入提示符,並且它的標準輸入、輸出和錯誤輸出都會顯示在控制臺上。這種模式也是大多數用戶非常熟悉的:登錄、執行一些命令、退出。當你退出後,shell也終止了。
    • 非交互式shell是bash script.sh這類的shell。在這種模式下,shell不與你進行交互,而是讀取存放在文件中的命令,並且執行它們。當它讀到文件的結尾EOF,shell也就終止了。
  • 登錄式shell(login shell)和非登陸式shell(no-login shell)
    • 需要輸入用戶名和密碼的shell就是登陸式shell。因此通常不管以何種方式登陸機器後用戶獲得的第一個shell就是login shell。不輸入密碼的ssh是公鑰打通的,某種意義上說也是輸入密碼的。
    • 非登陸式的就是在登陸後啟動bash等,即不是遠程登陸到主機這種。

對於常用環境變量設置文件,整理出如下加載情況表:

文件 非交互+登陸式 交互+登陸式 交互+非登陸式 非交互+非登陸式
/etc/profile 加載 加載 - -
/etc/bashrc 加載 加載 - -
~/.bash_profile 加載 加載 - -
~/.bashrc 加載 加載 加載 -
BASH_ENV - - - 加載

執行腳本,如bash script.sh是屬於non-login + non-interactive。

解決思路

因而,執行命令docker exec f4af9b sh -c ‘bash /tmp/build.sh‘對於docker容器來說是屬於non-login + non-interactive。

將上面的bash /tmp/build.sh改為bash --login /tmp/build.sh變為登錄shell,就可以讀取/etc/profile和~/.bash_profile等文件。

或者在執行bash /tmp/build.sh時在build.sh加入export LANG="en_US.UTF-8"手動設置。

常見的shell變量

PATH:決定了shell將到哪些目錄中尋找命令或程序
HOME:當前用戶主目錄
MAIL:是指當前用戶的郵件存放目錄。
SHELL:是指當前用戶用的是哪種Shell。
HISTSIZE:是指保存歷史命令記錄的條數
LOGNAME:是指當前用戶的登錄名。
HOSTNAME:是指主機的名稱,許多應用程序如果要用到主機名的話,通常是從這個環境變量中來取得的。
LANG/LANGUGE:是和語言相關的環境變量,使用多種語言的用戶可以修改此環境變量。
PS1:是基本提示符,對於root用戶是#,對於普通用戶是$。
PS2:是附屬提示符,默認是">"。

Docker中執行Shell出現亂碼