- 論壇徽章:
- 0
|
本帖最后由 xiaozi0lei 于 2013-03-05 13:32 編輯
轉(zhuǎn)載請注明出處,謝謝!
http://blog.sina.com.cn/s/blog_5e2308c80101hssf.html
- #!/usr/bin//perl
- #
- # Copyright (C) 2002-2003 RealVNC Ltd.
- # Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved.
- #
- # This is free software; you can redistribute it and/or modify
- # it under the terms of the GNU General Public License as published by
- # the Free Software Foundation; either version 2 of the License, or
- # (at your option) any later version.
- #
- # This software is distributed in the hope that it will be useful,
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- # GNU General Public License for more details.
- #
- # You should have received a copy of the GNU General Public License
- # along with this software; if not, write to the Free Software
- # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
- # USA.
- #
- # # # # # # # # # # # # # # # # # # # # # # # # # #
- # This document is translated and commented by 弦上風(fēng).
- # 本文檔由弦上風(fēng)注釋翻譯。
- # If you have any questions and good comments, please feel free to tell me.
- # 如果你有任何問題或者好的建議,請積極聯(lián)系我。
- # @弦上風(fēng)
- # # # # # # # # # # # # # # # # # # # # # # # # # #
- #此腳本用來啟動一個X VNC 服務(wù)器
- # vncserver - wrapper script to start an X VNC server.
- #
- #首先,保證我們在一個穩(wěn)定可靠的環(huán)境進(jìn)行操作
- # First make sure we're operating in a sane environment.
- #
- #調(diào)用腳本下方的SanityCheck子過程
- &SanityCheck();
- #全局變量,可以針對自己的site進(jìn)行自定義配置
- # Global variables. You may want to configure some of these for your site.
- #
- #初始化顯示的分辨率,默認(rèn)分辨率
- $geometry = "1024x768";
- #顏色深度,默認(rèn)色深
- $depth = 16;
- #定義vncJavaFiles的目錄
- $vncJavaFiles = (((-d "/usr/share/vnc/classes") && "/usr/share/vnc/classes") ||
- ((-d "/usr/local/vnc/classes") && "/usr/local/vnc/classes"));
- #定義用戶vnc目錄
- $vncUserDir = "$ENV{HOME}/.vnc";
- #定義X驗證文件目錄
- $xauthorityFile = "$ENV{XAUTHORITY}" || "$ENV{HOME}/.Xauthority";
- #定義默認(rèn)的Xstartup啟動腳本
- $defaultXStartup
- = ("#!/bin/sh\n\n".
- "[ -r \$HOME/.Xresources ] && xrdb \$HOME/.Xresources\n".
- "xsetroot -solid grey\n".
- "vncconfig -iconic &\n".
- "xterm -geometry 80x24+10+10 -ls -title \"\$VNCDESKTOP Desktop\" &\n".
- "twm &\n");
-
- #獲取hostname
- chop($host = `uname -n`);
- #檢查命令行選項
- # Check command line options
- #分析命令行中的參數(shù)
- &ParseOptions("-geometry",1,"-depth",1,"-pixelformat",1,"-name",1,"-kill",1,
- "-help",0,"-h",0,"--help",0);
- #如果命令行中包括"-help","-h","--help",輸出使用幫助
- &Usage() if ($opt{'-help'} || $opt{'-h'} || $opt{'--help'});
- #如果命令行中帶有"-kill"參數(shù),調(diào)用Kill子過程
- &Kill() if ($opt{'-kill'});
- #如果你想使用默認(rèn)的分辨率,顏色深度和像素格式來匹配當(dāng)前的X顯示,請去掉下面這行注釋
- # Uncomment this line if you want default geometry, depth and pixelformat
- # to match the current X display:
- # &GetXDisplayDefaults();
- #讀取命令行中的分辨率設(shè)置,賦給分辨率全局變量
- if ($opt{'-geometry'}) {
- $geometry = $opt{'-geometry'};
- }
- #讀取命令行中的顏色深度設(shè)置,賦給顏色深度全局變量
- if ($opt{'-depth'}) {
- $depth = $opt{'-depth'};
- $pixelformat = "";
- }
- #讀取命令行中的像素格式設(shè)置,賦給像素格式全局變量
- if ($opt{'-pixelformat'}) {
- $pixelformat = $opt{'-pixelformat'};
- }
- #調(diào)用檢查分辨率和色深的子過程
- &CheckGeometryAndDepth();
- #如果沒有則創(chuàng)建用戶的vnc目錄
- # Create the user's vnc directory if necessary.
- #如果不存在用戶的vnc目錄
- if (!(-e $vncUserDir)) {
- #如果無法創(chuàng)建用戶的vnc目錄,退出并輸出錯誤提示信息
- if (!mkdir($vncUserDir,0755)) {
- die "$prog: Could not create $vncUserDir.\n";
- }
- }
-
- #保證用戶有密碼
- # Make sure the user has a password.
- #獲取passwd文件的權(quán)限屬性
- ($z,$z,$mode) = stat("$vncUserDir/passwd");
- #如果不存在passwd文件或者非擁有者對該文件具有可讀寫權(quán)限,提示用戶需要設(shè)置密碼
- if (!(-e "$vncUserDir/passwd") || ($mode & 077)) {
- warn "\nYou will require a password to access your desktops.\n\n";
- #從外部系統(tǒng)執(zhí)行vncpasswd -q $vncUserDir/passwd命令
- system("vncpasswd -q $vncUserDir/passwd");
- #判斷外部系統(tǒng)退出狀態(tài)是否為O,不為0則提示錯誤退出,0是正常退出狀態(tài)
- if (($? >> 8) != 0) {
- exit 1;
- }
- }
- #拿到display號
- # Find display number.
- #如果剩余的命令參數(shù)的數(shù)量大于0且第一個參數(shù)是以:開頭,后面是整數(shù)
- if ((@ARGV > 0) && ($ARGV[0] =~ /^:(\d+)$/)) {
- #將$1中的值賦給變量$displayNumber
- $displayNumber = $1;
- #從左邊彈出一個參數(shù)
- shift(@ARGV);
- #檢查輸入的display號是否被占用,若被占用,則退出并輸出錯誤提示信息
- if (!&CheckDisplayNumber($displayNumber)) {
- die "A VNC server is already running as :$displayNumber\n";
- }
- #如果剩余的命令參數(shù)的數(shù)量大于0且第一個參數(shù)不是-開頭,則輸出使用說明
- } elsif ((@ARGV > 0) && ($ARGV[0] !~ /^-/)) {
- &Usage();
- #如果以上都不符號,則自動分配display號
- } else {
- $displayNumber = &GetDisplayNumber();
- }
- #將5900加上有效的displaynumber賦給變量vncPort
- $vncPort = 5900 + $displayNumber;
- #定義用戶vnc的log路徑
- $desktopLog = "$vncUserDir/$host:$displayNumber.log";
- #刪除之前的vnc log
- unlink($desktopLog);
- #制作一個X server的cookie,作為種子,當(dāng)前時間,我們的PID,passwd加密格式的一部分
- # Make an X server cookie - use as the seed the sum of the current time, our
- # PID and part of the encrypted form of the password. Ideally we'd use
- # /dev/urandom, but that's only available on Linux.
- #用srand函數(shù)生成隨機數(shù)種子提供給rand函數(shù)使用
- srand(time+$+unpack("L",`cat $vncUserDir/passwd`));
- $cookie = "";
- for (1..16) {
- #生成32位的隨機數(shù)作為cookie
- $cookie .= sprintf("%02x", int(rand(256)) % 256);
- }
-
- #調(diào)用外部命令為當(dāng)前的displayNumber在xauth驗證文件添加cookie
- system("xauth -f $xauthorityFile add $host:$displayNumber . $cookie");
- system("xauth -f $xauthorityFile add $host/unix:$displayNumber . $cookie");
- #如果數(shù)組%opt中的-name參數(shù)有值,則將值賦給變量$desktopName
- if ($opt{'-name'}) {
- $desktopName = $opt{'-name'};
- #如果沒有,則取默認(rèn)的組合值
- } else {
- $desktopName = "$host:$displayNumber ($ENV{USER})";
- }
- #開始啟動X VNC服務(wù)器
- # Now start the X VNC Server
- #將之前得到的所有變量連接起來,形成一條完整的命令
- $cmd = "Xvnc :$displayNumber";
- $cmd .= " -desktop " . "edString($desktopName);
- $cmd .= " -httpd $vncJavaFiles" if ($vncJavaFiles);
- $cmd .= " -auth $xauthorityFile";
- $cmd .= " -geometry $geometry" if ($geometry);
- $cmd .= " -depth $depth" if ($depth);
- $cmd .= " -pixelformat $pixelformat" if ($pixelformat);
- $cmd .= " -rfbwait 30000";
- $cmd .= " -rfbauth $vncUserDir/passwd";
- $cmd .= " -rfbport $vncPort";
- $cmd .= " -pn";
- #添加字庫和顏色相關(guān)
- # Add font path and color database stuff here, e.g.:
- #
- # $cmd .= " -fp /usr/lib/X11/fonts/misc/,/usr/lib/X11/fonts/75dpi/";
- # $cmd .= " -co /usr/lib/X11/rgb";
- #
- #循環(huán)取出剩余的命令行參數(shù)加到命令的末尾
- foreach $arg (@ARGV) {
- $cmd .= " " . "edString($arg);
- }
- #將命令執(zhí)行結(jié)果輸出到vnc目錄下的log中,包括標(biāo)準(zhǔn)錯誤輸出
- $cmd .= " >> " . "edString($desktopLog) . " 2>&1";
- #運行cmd命令并記錄進(jìn)程ID
- # Run $cmd and record the process ID.
- #定義進(jìn)程ID文件路徑
- $pidFile = "$vncUserDir/$host:$displayNumber.pid";
- #執(zhí)行cmd中的命令并將進(jìn)程ID寫入文件$pidFile
- system("$cmd & echo \$! >$pidFile");
- #啟動Xvnc
- # Give Xvnc a chance to start up
- #等待3秒
- sleep(3);
- #提示vncserver啟動成功
- warn "\nNew '$desktopName' desktop is $host:$displayNumber\n\n";
- #創(chuàng)建用戶的啟動腳本
- # Create the user's xstartup script if necessary.
- #如果用戶啟動腳本不存在
- if (!(-e "$vncUserDir/xstartup")) {
- #提示創(chuàng)建默認(rèn)的啟動腳本,存放在vnc用戶目錄下
- warn "Creating default startup script $vncUserDir/xstartup\n";
- #以寫權(quán)限打開用戶啟動腳本
- open(XSTARTUP, ">$vncUserDir/xstartup");
- #將默認(rèn)啟動參數(shù)寫入啟動腳本中
- print XSTARTUP $defaultXStartup;
- #關(guān)閉腳本文件
- close(XSTARTUP);
- #給腳本文件增加755的權(quán)限
- chmod 0755, "$vncUserDir/xstartup";
- }
- #運行用戶腳本文件
- # Run the X startup script.
- #提示按照用戶目錄下的腳本啟動程序
- warn "Starting applications specified in $vncUserDir/xstartup\n";
- #提示log文件存放在用戶目錄下
- warn "Log file is $desktopLog\n\n";
- #如果存在unix domain socket,則設(shè)置環(huán)境變量$DISPLAY=:n,否則使用TCP socket,設(shè)置環(huán)境變量$DISPLAY=host:n
- # If the unix domain socket exists then use that (DISPLAY=:n) otherwise use
- # TCP (DISPLAY=host:n)
- #如果tmp目錄下存在對應(yīng)的socket文件或者usr的sockets目錄下存在對應(yīng)的文件
- if (-e "/tmp/.X11-unix/X$displayNumber" ||
- -e "/usr/spool/sockets/X11/$displayNumber")
- {
- #設(shè)置環(huán)境變量DISPLAY=:n
- $ENV{DISPLAY}= ":$displayNumber";
- } else {
- #否則設(shè)置環(huán)境變量DISPLAY=host:n
- $ENV{DISPLAY}= "$host:$displayNumber";
- }
- #設(shè)置環(huán)境變量$VNCDESKTOP
- $ENV{VNCDESKTOP}= $desktopName;
- #調(diào)用外部命令執(zhí)行xstartup腳本并將標(biāo)準(zhǔn)輸出和錯誤追加到日志里
- system("$vncUserDir/xstartup >> " . "edString($desktopLog) . " 2>&1 &");
- exit;
- ###############################################################################
- #
- # CheckGeometryAndDepth simply makes sure that the geometry and depth values
- # are sensible.
- #簡單的檢查分辨率和顏色深度
- sub CheckGeometryAndDepth
- {
- #如果分辨率是按照整數(shù)x整數(shù)格式
- if ($geometry =~ /^(\d+)x(\d+)$/) {
- #取第一個整數(shù)作為寬,第二個整數(shù)作為高
- $width = $1; $height = $2;
- #如果寬和高其中一個小于1,退出并提示錯誤信息
- if (($width<1) || ($height<1)) {
- die "$prog: geometry $geometry is invalid\n";
- }
- #保證分辨率的寬是4的倍數(shù)
- while (($width % 4)!=0) {
- $width = $width + 1;
- }
- #保證分辨率的高是2的倍數(shù)
- while (($height % 2)!=0) {
- $height = $height + 1;
- }
- #算出分辨率并賦給變量$geometry
- $geometry = "${width}x$height";
- } else {
- #如果分辨率格式不對,退出并提示錯誤
- die "$prog: geometry $geometry is invalid\n";
- }
- #如果顏色深度不是8到32,退出并提示錯誤
- if (($depth < 8) || ($depth > 32)) {
- die "Depth must be between 8 and 32\n";
- }
- }
- #從最低有效的display號匹配
- # GetDisplayNumber gets the lowest available display number. A display number
- # n is taken if something is listening on the VNC server port (5900+n) or the
- # X server port (6000+n).
- #
- sub GetDisplayNumber
- {
- #檢查1到99的display號是否被占用,沒被占用就返回該號碼,全被占用則退出輸出錯誤提示信息
- foreach $n (1..99) {
- if (&CheckDisplayNumber($n)) {
- return $n+0; # Bruce Mah's workaround for bug in perl 5.005_02
- }
- }
-
- die "$prog: no free display number on $host.\n";
- }
- #檢查DisplayNumber,判斷是否命令行給定的DisplayNumber是可用的。判斷給定端口是否被其他程序占用
- # CheckDisplayNumber checks if the given display number is available. A
- # display number n is taken if something is listening on the VNC server port
- # (5900+n) or the X server port (6000+n).
- #
- sub CheckDisplayNumber
- {
- local ($n) = @_;
-
- #Perl的函數(shù)Socket的格式為:Socket(FILE,Domain,Type,Protocol);
- #其中:
- #FILE 綁定一個套接字句柄(類似于打開文件的句柄);
- #Domain 表示套接字的協(xié)議域類型。它可以定義為Internet域,其值為2,也可以定義為UNIX域,如果把這個變量賦值為1表示域的類型為UNIX域。如果這個變量付值為2,則表示定義類型為Internet。我們常用的是的套接字協(xié)議族為Internet協(xié)議族。
- #Type 表示套接字類型,定義為SOCK_STREAM類型,表示的是基于流傳輸模式的TCP套接字。定義為SOCK_DGRAM類型,表示為基于簡單數(shù)據(jù)傳遞的UDP套接字。
- #Protocol 表示套接字的協(xié)議號,這個協(xié)議號可以通過Perl內(nèi)置函數(shù)getprotobyname()得到
- #打開一個internet域的TCP套接字,如果失敗,退出并提示錯誤信息
- socket(S, $AF_INET, $SOCK_STREAM, 0) || die "$prog: socket failed: $!\n";
- #設(shè)置socket選項,并捕獲錯誤信息
- eval 'setsockopt(S, &SOL_SOCKET, &SO_REUSEADDR, pack("l", 1))';
- #如果綁定失敗,關(guān)閉套接字,返回0
- if (!bind(S, pack('S n x12', $AF_INET, 6000 + $n))) {
- close(S);
- return 0;
- }
- close(S);
- #打開一個internet域的TCP套接字,如果失敗,退出并提示錯誤信息
- socket(S, $AF_INET, $SOCK_STREAM, 0) || die "$prog: socket failed: $!\n";
- #設(shè)置socket選項,并捕獲錯誤信息
- eval 'setsockopt(S, &SOL_SOCKET, &SO_REUSEADDR, pack("l", 1))';
- #如果綁定失敗,關(guān)閉套接字,返回0
- if (!bind(S, pack('S n x12', $AF_INET, 5900 + $n))) {
- close(S);
- return 0;
- }
- close(S);
- #如果tmp目錄下存在-lock,提示警告信息
- if (-e "/tmp/.X$n-lock") {
- warn "\nWarning: $host:$n is taken because of /tmp/.X$n-lock\n";
- warn "Remove this file if there is no X server $host:$n\n";
- return 0;
- }
- #如果tmp目錄下存在socket文件,提示警告信息
- if (-e "/tmp/.X11-unix/X$n") {
- warn "\nWarning: $host:$n is taken because of /tmp/.X11-unix/X$n\n";
- warn "Remove this file if there is no X server $host:$n\n";
- return 0;
- }
- #如果/usr/spool/sockets目錄下存在socket文件,提示警告信息
- if (-e "/usr/spool/sockets/X11/$n") {
- warn("\nWarning: $host:$n is taken because of ".
- "/usr/spool/sockets/X11/$n\n");
- warn "Remove this file if there is no X server $host:$n\n";
- return 0;
- }
- return 1;
- }
復(fù)制代碼 |
|