เชลล์สคริปต์เบื้องต้น ตอนที่ 3 - ตัวแปรสภาพแวดล้อม

อัดรูปดิจิตอล ทำสมุดภาพของคุณเอง
รอรับได้. ท่องเที่ยว แต่งงาน ฯลฯ

www.tanabutr.co.th/photobook


ตัวแปรสภาพแวดล้อม

ตัวแปรที่ใช้ในเชลล์จะมีสองแบบคือตัวแปรธรรมดากับตัวแปรสภาพแวดล้อม (environment variable). ตัวแปรสภาพแวดล้อมจริงๆแล้วก็คือตัวแปรธรรมดาแต่มีผลที่โปรแกรมที่รันในเชลล์นั้นจะสืบทอดตัวแปรสภาพแวดล้อมและค่านั้นไปด้วย. ตัวอย่างตัวแปรสภาพแวดล้อมที่เราคุ้นเคยกันเช่น PATH เป็นต้น.

การสร้างตัวแปรสภาพแวดล้อมเหมือนกับการสร้างตัวแปรทั่วไป. แต่หลังจากที่สร้างตัวแปรทั่วไปแล้วต้องประกาศตัวแปรนั้นให้เป็นตัวแปรสภาพแวดล้อมด้วยคำสั่ง export.

$ MY_ENV_VAR="example of environment variable"
$ export MY_ENV_VAR

หรือจะตั้งแค่ตัวแปรและประกาศตัวแปรสภาพแวดล้อมพร้อมๆกันก็ได้.

$ export MY_ENV_VAR="example of environment variable"

ตัวแปรสภาพแวดล้อมมักจำใช้ชื่อตัวแปรเป็นตัวอักษรตัวใหญ่แต่ไม่จำเป็น. เราลองมาดูผลกระทบของตัวแปรสภาพแวดล้อมต่อโปรแกรมที่รันในเชลล์นั้นๆดู.

สมมติว่าเรามีเชลล์สคริปต์ที่แสดงค่าตัวแปรตามตัวอย่างต่อไปนี้.

#!/bin/sh
# file: env.sh
echo $MY_ENV_VAR
echo $MY_VAR

เชลล์สคริปต์นี้ไม่ได้ทำอะไรพิสดาร, แค่แสดงค่าของตัวแปร MY_ENV_VAR กับ MY_VAR เท่านั้น. ที่นี้เราลองรันในเชลล์ที่มีตัวแปรสภาพแวดล้อม MY_ENV_VAR และตัวแปรธรรมดา MY_VAR ดูว่าจะได้ผลอย่างไรดู.

$ export MY_ENV_VAR="example of environment variable"
$ MY_VAR="Normal variable"
$ ./env.sh
example of environment variable
 
$ . env.sh
example of environment variable
Normal variable

ผลของการรันเชลล์สคริปต์จะไม่เหมือนกัน. ทำไม? การรันเชลล์สคริปต์แบบแรกเชลล์ที่รันอยู่จะเรียกเชลล์ตัวใหม่ (สร้างโปรเซสใหม่) และเชลล์ตัวใหม่จะเป็นตัวกระทำการ. เชลล์ตัวใหม่ในที่นี้คือบรรทัด #!/bin/sh นั่นเอง. เชลล์ (โปรแกรม) ที่เกิดใหม่สืบทอดตัวแปรสภาพแวดล้อม MY_ENV_VAR มาด้วยทำให้แสดงผลได้. แต่ไม่สามารถแสดงค่าของตัวแปร MY_VAR ได้เพราะไม่ใช้ตัวแปรสภาพแวดล้อม (ไม่สืบทอดไปสู่โปรแกรมอื่น).

ส่วนการรันเชลล์สคริปต์แบบที่สองโดยใช้ "." (dot). เป็นการใช้เชลล์ที่ทำงานอยู่ในปัจจุบันอ่านไฟล์ env.sh ไม่ได้เป็นการสร้างเชลล์ใหม่. ดังนั้นจึงสามารถแสดงค่าของตัวแปรทั้งสองตัวได้. คำสั่งที่เทียบเท่ากับ "." คือ source ใช้สำหรับอ่านข้อมูลเข้าไปในเชลล์ที่ใช้อยู่. ตัวอย่างเช่นในไฟล์ ~/.bashrc มักจะตั้งค่าตัวแปรต่างๆไว้. ไฟล์นี้จะถูกอ่าน (ถูกกระทำการ) ตอนที่เชลล์เริ่มทำงาน. ถ้ามีการแก้ไขไฟล์นี้แล้วอยากให้มีผลทันทีโดยไม่ต้องเริ่มเชลล์ใหม่ก็เพิ่งแค่ source ~/.bashrc เรียกอ่านเนื้อหาในไฟล์นั้นโดยใช้เชลล์ที่ทำงานอยู่ในปัจจุบัน.

ดูค่าตัวแปรสภาพแวดล้อม

เราจะรู้ได้อย่างไรว่ามีตัวแปรสภาพแวดล้อมอะไรบ้างในขณะนี้? คำสั่งที่ใช้บอกตัวแปรสภาพแวดล้อมก็คือคำสั่งเดียวกันกับที่ใช้ประกาศตัวแปรสภาพแวดล้อมซึ่งก็คือ export.

$ export
declare -x CC="gcc"
declare -x CLASSPATH="/opt/blackdown-jdk-1.4.1/jre/lib/rt.jar:."
declare -x COLORTERM="gnome-terminal"
declare -x CONFIG_PROTECT="/var/bind /usr/lib/mozilla/defaults/pref 
/usr/X11R6/lib/X11/xkb /usr/kde/3.2/share/config /usr/kde/3.1/share/config 
/usr/share/texmf/tex/generic/config/ /usr/share/texmf/tex/platex/config/ 
/usr/share/texmf/dvips/config/ /usr/share/texmf/dvipdfm/config/ 
/usr/share/texmf/xdvi/ /usr/share/config"
declare -x CONFIG_PROTECT_MASK="/etc/gconf /etc/terminfo"
declare -x CVSROOT=":pserver:poonlap@linux.thai.net:/home/cvs"
declare -x CVS_RSH="ssh"
declare -x CXX="g++"
declare -x DESKTOP_SESSION="gnome"
declare -x DISPLAY=":0.0"
declare -x EDITOR="/usr/bin/vim"
declare -x GDK_USE_XFT="1"
declare -x GDMSESSION="gnome"
declare -x GLIBC_SSP_CHECKED="1"
declare -x GNOME_DESKTOP_SESSION_ID="Default"
declare -x GNOME_KEYRING_SOCKET="/tmp/keyring-N1Rd2c/socket"
declare -x GTK_RC_FILES="/etc/gtk/gtkrc:/home/poonlap/.gtkrc-1.2-gnome2"
declare -x GUILE_LOAD_PATH="/usr/share/guile/1.6"
declare -x G_BROKEN_FILENAMES="1"
declare -x HOME="/home/poonlap"
declare -x HOSTNAME="justice"
declare -x INFODIR="/usr/share/info"
declare -x INFOPATH="/usr/share/info:/usr/share/gcc-data/i686-pc-linux-gnu/3.3
/info"
declare -x INPUTRC="/etc/inputrc"
declare -x JAVAC="/opt/blackdown-jdk-1.4.1/bin/javac"
declare -x JAVA_HOME="/opt/blackdown-jdk-1.4.1"
declare -x JDK_HOME="/opt/blackdown-jdk-1.4.1"
declare -x KDEDIR="/usr/kde/3.2"
declare -x KDEDIRS="/usr"
declare -x LESS="-R"
declare -x LESSOPEN="|lesspipe.sh %s"
declare -x LOGNAME="poonlap"
declare -x LS_COLORS="no=00:fi=00:di=01;34:ln=01;36:pi=40;33:so=01;35:do=01;35:bd=40;33;01
:cd=40;33;01:or=01;05;37;41:mi=01;05;37;41:ex=01;32:*.cmd=01;32:*.exe=01;32:*.
com=01;32:*.btm=01;32:*.bat=01;32:*.sh=01;32:*.csh=01;32:*.tar=01;31:*.tgz=01;
31:*.arj=01;31:*.taz=01;31:*.lzh=01;31:*.zip=01;31:*.z=01;31:*.Z=01;31:*.gz=01;
31:*.bz2=01;31:*.bz=01;31:*.tz=01;31:*.deb=01;31:*.rpm=01;31:*.rar=01;31:*.ace=
01;31:*.zoo=01;31:*.cpio=01;31:*.jpg=01;35:*.jpeg=01;35:*.gif=01;35:*.bmp=01;35
:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png
=01;35:*.mng=01;35:*.xcf=01;35:*.pcx=01;35:*.mpg=01;35:*.mpeg=01;35:*.m2v=01;35
:*.avi=01;35:*.mkv=01;35:*.ogm=01;35:*.mp4=01;35:*.m4v=01;35:*.mp4v=01;35:*.mov
=01;35:*.qt=01;35:*.wmv=01;35:*.asf=01;35:*.rm=01;35:*.rmvb=01;35:*.flc=01;35:*
.fli=01;35:*.gl=01;35:*.dl=01;35:"
declare -x MANPATH="/usr/share/man:/usr/local/share/man:/usr/share/gcc-data/i686-pc-linux-
gnu/3.3/man:/usr/share/man:/opt/blackdown-jdk-1.4.1/man:/usr/qt/3/doc/man:/opt/
vmware/man"
declare -x MOZILLA_FIVE_HOME="/usr/lib/mozilla"
declare -x MY_ENV_VAR="example of environment variable"
declare -x OLDPWD="/home/poonlap"
declare -x PAGER="/usr/bin/less"
declare -x PATH="/bin:/usr/bin:/usr/local/bin:/opt/bin:/usr/i686-pc-linux-gnu/gcc-bin/3.3:
/opt/Acrobat5:/usr/X11R6/bin:/opt/blackdown-jdk-1.4.1/bin:/opt/blackdown-jdk-1.
4.1/jre/bin:/usr/qt/3/bin:/usr/kde/3.2/bin:/usr/kde/3.1/bin:/opt/firebird/bin:
/opt/vmware/bin"
declare -x PS1="\\[\\033[01;32m\\]\\u@\\h \\[\\033[01;34m\\]\\W \\\$ \\[\\033[0
0m\\]"
declare -x PWD="/home/poonlap/tmp"
declare -x QMAKESPEC="linux-g++"
declare -x QTDIR="/usr/qt/3"
declare -x SESSION_MANAGER="local/justice:/tmp/.ICE-unix/7010"
declare -x SHELL="/bin/bash"
declare -x SHLVL="1"
declare -x SSH_AGENT_PID="7031"
declare -x SSH_AUTH_SOCK="/tmp/ssh-mqxqiU7010/agent.7010"
declare -x TERM="xterm"
declare -x USER="poonlap"
declare -x USERNAME="poonlap"
declare -x WINDOWID="21507072"
declare -x XAUTHORITY="/home/poonlap/.Xauthority"
declare -x XINITRC="/etc/X11/xinit/xinitrc"
declare -x XPSERVERLIST=""

จากตัวอย่างจะเห็นว่ามีตัวแปรสภาพแวดล้อมมากมายที่ตั้วค่าไว้อัตโนมัติในระบบ. คำสั่งที่ใช้แสดงตัวแปรสภาพแวดล้อมและค่าอีกคำสั่งคือ printenv.

ถ้าต้องการเปลี่ยนตัวแปรสภาพแวดล้อมเป็นตัวแปรธรรมดาก็ใช้ตัวเลือก -n ร่วมกับคำสั่ง export เช่น.

$ export -n MY_ENV_VAR