免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 2661 | 回复: 4
打印 上一主题 下一主题

vncserver注释,不当之处请指正(1) [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2013-03-05 13:24 |只看该作者 |倒序浏览
本帖最后由 xiaozi0lei 于 2013-03-05 13:32 编辑

转载请注明出处,谢谢!
http://blog.sina.com.cn/s/blog_5e2308c80101hssf.html


  1. #!/usr/bin//perl
  2. #
  3. #  Copyright (C) 2002-2003 RealVNC Ltd.
  4. #  Copyright (C) 1999 AT&T Laboratories Cambridge.  All Rights Reserved.
  5. #
  6. #  This is free software; you can redistribute it and/or modify
  7. #  it under the terms of the GNU General Public License as published by
  8. #  the Free Software Foundation; either version 2 of the License, or
  9. #  (at your option) any later version.
  10. #
  11. #  This software is distributed in the hope that it will be useful,
  12. #  but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. #  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. #  GNU General Public License for more details.
  15. #
  16. #  You should have received a copy of the GNU General Public License
  17. #  along with this software; if not, write to the Free Software
  18. #  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,
  19. #  USA.
  20. #
  21. #  #  #  #  #  #  #  #  #  #  #  #  #  #  #  #  #  #  #  #  #  #  #  #  #  #
  22. #  This document is translated and commented by 弦上风.
  23. #  本文档由弦上风注释翻译。
  24. #  If you have any questions and good comments, please feel free to tell me.
  25. #  如果你有任何问题或者好的建议,请积极联系我。
  26. #  @弦上风
  27. #  #  #  #  #  #  #  #  #  #  #  #  #  #  #  #  #  #  #  #  #  #  #  #  #  #

  28. #此脚本用来启动一个X VNC 服务器
  29. # vncserver - wrapper script to start an X VNC server.
  30. #

  31. #首先,保证我们在一个稳定可靠的环境进行操作
  32. # First make sure we're operating in a sane environment.
  33. #
  34. #调用脚本下方的SanityCheck子过程
  35. &SanityCheck();

  36. #全局变量,可以针对自己的site进行自定义配置
  37. # Global variables.  You may want to configure some of these for your site.
  38. #
  39. #初始化显示的分辨率,默认分辨率
  40. $geometry = "1024x768";
  41. #颜色深度,默认色深
  42. $depth = 16;

  43. #定义vncJavaFiles的目录
  44. $vncJavaFiles = (((-d "/usr/share/vnc/classes") && "/usr/share/vnc/classes") ||
  45.                  ((-d "/usr/local/vnc/classes") && "/usr/local/vnc/classes"));
  46. #定义用户vnc目录
  47. $vncUserDir = "$ENV{HOME}/.vnc";
  48. #定义X验证文件目录
  49. $xauthorityFile = "$ENV{XAUTHORITY}" || "$ENV{HOME}/.Xauthority";

  50. #定义默认的Xstartup启动脚本
  51. $defaultXStartup
  52.     = ("#!/bin/sh\n\n".
  53.        "[ -r \$HOME/.Xresources ] && xrdb \$HOME/.Xresources\n".
  54.        "xsetroot -solid grey\n".
  55.        "vncconfig -iconic &\n".
  56.        "xterm -geometry 80x24+10+10 -ls -title \"\$VNCDESKTOP Desktop\" &\n".
  57.        "twm &\n");
  58.           
  59. #获取hostname
  60. chop($host = `uname -n`);

  61. #检查命令行选项
  62. # Check command line options
  63. #分析命令行中的参数
  64. &ParseOptions("-geometry",1,"-depth",1,"-pixelformat",1,"-name",1,"-kill",1,
  65.               "-help",0,"-h",0,"--help",0);

  66. #如果命令行中包括"-help","-h","--help",输出使用帮助
  67. &Usage() if ($opt{'-help'} || $opt{'-h'} || $opt{'--help'});

  68. #如果命令行中带有"-kill"参数,调用Kill子过程
  69. &Kill() if ($opt{'-kill'});

  70. #如果你想使用默认的分辨率,颜色深度和像素格式来匹配当前的X显示,请去掉下面这行注释
  71. # Uncomment this line if you want default geometry, depth and pixelformat
  72. # to match the current X display:

  73. # &GetXDisplayDefaults();

  74. #读取命令行中的分辨率设置,赋给分辨率全局变量
  75. if ($opt{'-geometry'}) {
  76.     $geometry = $opt{'-geometry'};
  77. }
  78. #读取命令行中的颜色深度设置,赋给颜色深度全局变量
  79. if ($opt{'-depth'}) {
  80.     $depth = $opt{'-depth'};
  81.     $pixelformat = "";
  82. }
  83. #读取命令行中的像素格式设置,赋给像素格式全局变量
  84. if ($opt{'-pixelformat'}) {
  85.     $pixelformat = $opt{'-pixelformat'};
  86. }
  87. #调用检查分辨率和色深的子过程
  88. &CheckGeometryAndDepth();

  89. #如果没有则创建用户的vnc目录
  90. # Create the user's vnc directory if necessary.

  91. #如果不存在用户的vnc目录
  92. if (!(-e $vncUserDir)) {
  93. #如果无法创建用户的vnc目录,退出并输出错误提示信息
  94.     if (!mkdir($vncUserDir,0755)) {
  95.         die "$prog: Could not create $vncUserDir.\n";
  96.     }
  97. }
  98.    
  99. #保证用户有密码
  100. # Make sure the user has a password.

  101. #获取passwd文件的权限属性
  102. ($z,$z,$mode) = stat("$vncUserDir/passwd");
  103. #如果不存在passwd文件或者非拥有者对该文件具有可读写权限,提示用户需要设置密码
  104. if (!(-e "$vncUserDir/passwd") || ($mode & 077)) {
  105.     warn "\nYou will require a password to access your desktops.\n\n";
  106. #从外部系统执行vncpasswd -q $vncUserDir/passwd命令
  107.     system("vncpasswd -q $vncUserDir/passwd");
  108. #判断外部系统退出状态是否为O,不为0则提示错误退出,0是正常退出状态
  109.     if (($? >> 8) != 0) {
  110.         exit 1;
  111.     }
  112. }

  113. #拿到display号
  114. # Find display number.

  115. #如果剩余的命令参数的数量大于0且第一个参数是以:开头,后面是整数
  116. if ((@ARGV > 0) && ($ARGV[0] =~ /^:(\d+)$/)) {
  117. #将$1中的值赋给变量$displayNumber
  118.     $displayNumber = $1;
  119. #从左边弹出一个参数
  120.     shift(@ARGV);
  121. #检查输入的display号是否被占用,若被占用,则退出并输出错误提示信息
  122.     if (!&CheckDisplayNumber($displayNumber)) {
  123.         die "A VNC server is already running as :$displayNumber\n";
  124.     }
  125. #如果剩余的命令参数的数量大于0且第一个参数不是-开头,则输出使用说明
  126. } elsif ((@ARGV > 0) && ($ARGV[0] !~ /^-/)) {
  127.     &Usage();
  128. #如果以上都不符号,则自动分配display号
  129. } else {
  130.     $displayNumber = &GetDisplayNumber();
  131. }
  132. #将5900加上有效的displaynumber赋给变量vncPort
  133. $vncPort = 5900 + $displayNumber;

  134. #定义用户vnc的log路径
  135. $desktopLog = "$vncUserDir/$host:$displayNumber.log";
  136. #删除之前的vnc  log
  137. unlink($desktopLog);

  138. #制作一个X server的cookie,作为种子,当前时间,我们的PID,passwd加密格式的一部分
  139. # Make an X server cookie - use as the seed the sum of the current time, our
  140. # PID and part of the encrypted form of the password.  Ideally we'd use
  141. # /dev/urandom, but that's only available on Linux.

  142. #用srand函数生成随机数种子提供给rand函数使用
  143. srand(time+$+unpack("L",`cat $vncUserDir/passwd`));
  144. $cookie = "";
  145. for (1..16) {
  146. #生成32位的随机数作为cookie
  147.     $cookie .= sprintf("%02x", int(rand(256)) % 256);
  148. }
  149.    
  150. #调用外部命令为当前的displayNumber在xauth验证文件添加cookie
  151. system("xauth -f $xauthorityFile add $host:$displayNumber . $cookie");
  152. system("xauth -f $xauthorityFile add $host/unix:$displayNumber . $cookie");

  153. #如果数组%opt中的-name参数有值,则将值赋给变量$desktopName
  154. if ($opt{'-name'}) {
  155.     $desktopName = $opt{'-name'};
  156. #如果没有,则取默认的组合值
  157. } else {
  158.     $desktopName = "$host:$displayNumber ($ENV{USER})";
  159. }

  160. #开始启动X VNC服务器
  161. # Now start the X VNC Server

  162. #将之前得到的所有变量连接起来,形成一条完整的命令
  163. $cmd = "Xvnc :$displayNumber";
  164. $cmd .= " -desktop " . "edString($desktopName);
  165. $cmd .= " -httpd $vncJavaFiles" if ($vncJavaFiles);
  166. $cmd .= " -auth $xauthorityFile";
  167. $cmd .= " -geometry $geometry" if ($geometry);
  168. $cmd .= " -depth $depth" if ($depth);
  169. $cmd .= " -pixelformat $pixelformat" if ($pixelformat);
  170. $cmd .= " -rfbwait 30000";
  171. $cmd .= " -rfbauth $vncUserDir/passwd";
  172. $cmd .= " -rfbport $vncPort";
  173. $cmd .= " -pn";

  174. #添加字库和颜色相关
  175. # Add font path and color database stuff here, e.g.:
  176. #
  177. # $cmd .= " -fp /usr/lib/X11/fonts/misc/,/usr/lib/X11/fonts/75dpi/";
  178. # $cmd .= " -co /usr/lib/X11/rgb";
  179. #

  180. #循环取出剩余的命令行参数加到命令的末尾
  181. foreach $arg (@ARGV) {
  182.     $cmd .= " " . "edString($arg);
  183. }
  184. #将命令执行结果输出到vnc目录下的log中,包括标准错误输出
  185. $cmd .= " >> " . "edString($desktopLog) . " 2>&1";

  186. #运行cmd命令并记录进程ID
  187. # Run $cmd and record the process ID.

  188. #定义进程ID文件路径
  189. $pidFile = "$vncUserDir/$host:$displayNumber.pid";
  190. #执行cmd中的命令并将进程ID写入文件$pidFile
  191. system("$cmd & echo \$! >$pidFile");

  192. #启动Xvnc
  193. # Give Xvnc a chance to start up

  194. #等待3秒
  195. sleep(3);
  196. #提示vncserver启动成功
  197. warn "\nNew '$desktopName' desktop is $host:$displayNumber\n\n";

  198. #创建用户的启动脚本
  199. # Create the user's xstartup script if necessary.

  200. #如果用户启动脚本不存在
  201. if (!(-e "$vncUserDir/xstartup")) {
  202. #提示创建默认的启动脚本,存放在vnc用户目录下
  203.     warn "Creating default startup script $vncUserDir/xstartup\n";
  204. #以写权限打开用户启动脚本
  205.     open(XSTARTUP, ">$vncUserDir/xstartup");
  206. #将默认启动参数写入启动脚本中
  207.     print XSTARTUP $defaultXStartup;
  208. #关闭脚本文件
  209.     close(XSTARTUP);
  210. #给脚本文件增加755的权限
  211.     chmod 0755, "$vncUserDir/xstartup";
  212. }

  213. #运行用户脚本文件
  214. # Run the X startup script.

  215. #提示按照用户目录下的脚本启动程序
  216. warn "Starting applications specified in $vncUserDir/xstartup\n";
  217. #提示log文件存放在用户目录下
  218. warn "Log file is $desktopLog\n\n";

  219. #如果存在unix domain socket,则设置环境变量$DISPLAY=:n,否则使用TCP socket,设置环境变量$DISPLAY=host:n
  220. # If the unix domain socket exists then use that (DISPLAY=:n) otherwise use
  221. # TCP (DISPLAY=host:n)

  222. #如果tmp目录下存在对应的socket文件或者usr的sockets目录下存在对应的文件
  223. if (-e "/tmp/.X11-unix/X$displayNumber" ||
  224.     -e "/usr/spool/sockets/X11/$displayNumber")
  225. {
  226. #设置环境变量DISPLAY=:n
  227.     $ENV{DISPLAY}= ":$displayNumber";
  228. } else {
  229. #否则设置环境变量DISPLAY=host:n
  230.     $ENV{DISPLAY}= "$host:$displayNumber";
  231. }
  232. #设置环境变量$VNCDESKTOP
  233. $ENV{VNCDESKTOP}= $desktopName;

  234. #调用外部命令执行xstartup脚本并将标准输出和错误追加到日志里
  235. system("$vncUserDir/xstartup >> " . "edString($desktopLog) . " 2>&1 &");

  236. exit;


  237. ###############################################################################
  238. #
  239. # CheckGeometryAndDepth simply makes sure that the geometry and depth values
  240. # are sensible.
  241. #简单的检查分辨率和颜色深度

  242. sub CheckGeometryAndDepth
  243. {
  244. #如果分辨率是按照整数x整数格式
  245.     if ($geometry =~ /^(\d+)x(\d+)$/) {
  246. #取第一个整数作为宽,第二个整数作为高
  247.                 $width = $1; $height = $2;
  248. #如果宽和高其中一个小于1,退出并提示错误信息
  249.                 if (($width<1) || ($height<1)) {
  250.                         die "$prog: geometry $geometry is invalid\n";
  251.                 }
  252. #保证分辨率的宽是4的倍数
  253.                 while (($width % 4)!=0) {
  254.                         $width = $width + 1;
  255.                 }

  256. #保证分辨率的高是2的倍数
  257.                 while (($height % 2)!=0) {
  258.                         $height = $height + 1;
  259.                 }
  260. #算出分辨率并赋给变量$geometry
  261.                 $geometry = "${width}x$height";
  262.     } else {
  263. #如果分辨率格式不对,退出并提示错误
  264.                 die "$prog: geometry $geometry is invalid\n";
  265.     }
  266. #如果颜色深度不是8到32,退出并提示错误
  267.     if (($depth < 8) || ($depth > 32)) {
  268.                 die "Depth must be between 8 and 32\n";
  269.     }
  270. }


  271. #从最低有效的display号匹配
  272. # GetDisplayNumber gets the lowest available display number.  A display number
  273. # n is taken if something is listening on the VNC server port (5900+n) or the
  274. # X server port (6000+n).
  275. #

  276. sub GetDisplayNumber
  277. {
  278. #检查1到99的display号是否被占用,没被占用就返回该号码,全被占用则退出输出错误提示信息
  279.     foreach $n (1..99) {
  280.         if (&CheckDisplayNumber($n)) {
  281.             return $n+0; # Bruce Mah's workaround for bug in perl 5.005_02
  282.         }
  283.     }
  284.    
  285.     die "$prog: no free display number on $host.\n";
  286. }


  287. #检查DisplayNumber,判断是否命令行给定的DisplayNumber是可用的。判断给定端口是否被其他程序占用
  288. # CheckDisplayNumber checks if the given display number is available.  A
  289. # display number n is taken if something is listening on the VNC server port
  290. # (5900+n) or the X server port (6000+n).
  291. #

  292. sub CheckDisplayNumber
  293. {
  294.     local ($n) = @_;
  295.        
  296. #Perl的函数Socket的格式为:Socket(FILE,Domain,Type,Protocol);
  297. #其中:
  298. #FILE 绑定一个套接字句柄(类似于打开文件的句柄);
  299. #Domain 表示套接字的协议域类型。它可以定义为Internet域,其值为2,也可以定义为UNIX域,如果把这个变量赋值为1表示域的类型为UNIX域。如果这个变量付值为2,则表示定义类型为Internet。我们常用的是的套接字协议族为Internet协议族。
  300. #Type 表示套接字类型,定义为SOCK_STREAM类型,表示的是基于流传输模式的TCP套接字。定义为SOCK_DGRAM类型,表示为基于简单数据传递的UDP套接字。
  301. #Protocol 表示套接字的协议号,这个协议号可以通过Perl内置函数getprotobyname()得到

  302. #打开一个internet域的TCP套接字,如果失败,退出并提示错误信息
  303.     socket(S, $AF_INET, $SOCK_STREAM, 0) || die "$prog: socket failed: $!\n";
  304. #设置socket选项,并捕获错误信息
  305.     eval 'setsockopt(S, &SOL_SOCKET, &SO_REUSEADDR, pack("l", 1))';
  306. #如果绑定失败,关闭套接字,返回0
  307.     if (!bind(S, pack('S n x12', $AF_INET, 6000 + $n))) {
  308.                 close(S);
  309.                 return 0;
  310.     }
  311.     close(S);

  312. #打开一个internet域的TCP套接字,如果失败,退出并提示错误信息
  313.     socket(S, $AF_INET, $SOCK_STREAM, 0) || die "$prog: socket failed: $!\n";
  314. #设置socket选项,并捕获错误信息
  315.     eval 'setsockopt(S, &SOL_SOCKET, &SO_REUSEADDR, pack("l", 1))';
  316. #如果绑定失败,关闭套接字,返回0
  317.     if (!bind(S, pack('S n x12', $AF_INET, 5900 + $n))) {
  318.                 close(S);
  319.                 return 0;
  320.     }
  321.     close(S);

  322. #如果tmp目录下存在-lock,提示警告信息
  323.     if (-e "/tmp/.X$n-lock") {
  324.                 warn "\nWarning: $host:$n is taken because of /tmp/.X$n-lock\n";
  325.                 warn "Remove this file if there is no X server $host:$n\n";
  326.                 return 0;
  327.     }

  328. #如果tmp目录下存在socket文件,提示警告信息
  329.     if (-e "/tmp/.X11-unix/X$n") {
  330.                 warn "\nWarning: $host:$n is taken because of /tmp/.X11-unix/X$n\n";
  331.                 warn "Remove this file if there is no X server $host:$n\n";
  332.                 return 0;
  333.     }

  334. #如果/usr/spool/sockets目录下存在socket文件,提示警告信息
  335.     if (-e "/usr/spool/sockets/X11/$n") {
  336.                 warn("\nWarning: $host:$n is taken because of ".
  337.              "/usr/spool/sockets/X11/$n\n");
  338.                 warn "Remove this file if there is no X server $host:$n\n";
  339.                 return 0;
  340.     }

  341.     return 1;
  342. }
复制代码

论坛徽章:
0
2 [报告]
发表于 2013-03-05 13:29 |只看该作者

  1. #
  2. # GetXDisplayDefaults uses xdpyinfo to find out the geometry, depth and pixel
  3. # format of the current X display being used.  If successful, it sets the
  4. # options as appropriate so that the X VNC server will use the same settings
  5. # (minus an allowance for window manager decorations on the geometry).  Using
  6. # the same depth and pixel format means that the VNC server won't have to
  7. # translate pixels when the desktop is being viewed on this X display (for
  8. # TrueColor displays anyway).
  9. #

  10. sub GetXDisplayDefaults
  11. {
  12. #定义本地标量和列表变量
  13.     local (@lines, @matchlines, $width, $height, $defaultVisualId, $i,
  14.            $red, $green, $blue);

  15. #wmDecorationWidth (class WmDecorationWidth)
  16. #For calculating maximum VNC window size.  Default  4.
  17. #wmDecorationHeight (class WmDecorationHeight)
  18. #For calculating maximum VNC window size.  Default  24.
  19. #不明白这两个变量是用来干嘛的,个人猜测是窗口的边框。decoration是装饰的意思,窗口渲染时,大小必须去掉装饰的长宽
  20.     $wmDecorationWidth = 4;        # a guess at typical size for window manager
  21.     $wmDecorationHeight = 24;        # decoration size

  22. #如果没有定义环境变量DISPLAY,就直接返回
  23.     return if (!defined($ENV{DISPLAY}));
  24. #利用unix下的xdpyinfo工具读取相关的显示信息,赋给数组@lines
  25.     @lines = `xdpyinfo 2>/dev/null`;

  26. #如果上一个外部命令执行错误,则直接返回
  27.     return if ($? != 0);

  28. #找到分辨率,将分辨率赋值给数组
  29.     @matchlines = grep(/dimensions/, @lines);
  30. #如果数组里有值
  31.     if (@matchlines) {
  32. #将数组中字符串通过正则表达式将宽和高取出赋给列表中的两个变量
  33.                 ($width, $height) = ($matchlines[0] =~ /(\d+)x(\d+) pixels/);

  34. #去掉装饰的长宽,个人理解是去掉边框
  35.                 $width -= $wmDecorationWidth;
  36.                 $height -= $wmDecorationHeight;

  37. #将得到的宽高赋给分辨率变量
  38.                 $geometry = "${width}x$height";
  39.     }

  40. #找到默认图像ID
  41.     @matchlines = grep(/default visual id/, @lines);
  42.     if (@matchlines) {
  43. #取出默认图像ID
  44.         ($defaultVisualId) = ($matchlines[0] =~ /id:\s+(\S+)/);

  45. #遍历数组@lines中所有的元素,查找默认图像ID对应的TrueColor,depth以及RGB
  46.         for ($i = 0; $i < @lines; $i++) {
  47.             if ($lines[$i] =~ /^\s*visual id:\s+$defaultVisualId$/) {
  48. #如果找不到TrueColor,depth,RGB任何一个,直接返回
  49.                         if (($lines[$i+1] !~ /TrueColor/) ||
  50.                                 ($lines[$i+2] !~ /depth/) ||
  51.                                 ($lines[$i+4] !~ /red, green, blue masks/))
  52.                         {
  53.                                 return;
  54.                         }
  55.                         last;
  56.             }
  57.         }
  58. #如果遍历的所有的元素,找不到匹配的元素,直接返回
  59.         return if ($i >= @lines);

  60. #将找到的默认色深赋给变量$depth
  61.         ($depth) = ($lines[$i+2] =~ /depth:\s+(\d+)/);
  62. #将找到的默认RGB色彩模式值赋给变量
  63.         ($red,$green,$blue)
  64.             = ($lines[$i+4]
  65.                =~ /masks:\s+0x([0-9a-f]+), 0x([0-9a-f]+), 0x([0-9a-f]+)/);

  66. #将十六进制转换成十进制
  67.         $red = hex($red);
  68.         $green = hex($green);
  69.         $blue = hex($blue);

  70. #计算红绿蓝然后得出像素格式,不懂图形学,不知道这些公式干嘛的...囧
  71.         if ($red > $blue) {
  72.             $red = int(log($red) / log(2)) - int(log($green) / log(2));
  73.             $green = int(log($green) / log(2)) - int(log($blue) / log(2));
  74.             $blue = int(log($blue) / log(2)) + 1;
  75.             $pixelformat = "rgb$red$green$blue";
  76.         } else {
  77.             $blue = int(log($blue) / log(2)) - int(log($green) / log(2));
  78.             $green = int(log($green) / log(2)) - int(log($red) / log(2));
  79.             $red = int(log($red) / log(2)) + 1;
  80.             $pixelformat = "bgr$blue$green$red";
  81.         }
  82.     }
  83. }


  84. #没明白这个子过程有什么用...把'替换成'"'"',然后再加上'',不明白意图~囧
  85. # quotedString returns a string which yields the original string when parsed
  86. # by a shell.
  87. #

  88. sub quotedString
  89. {
  90.     local ($in) = @_;

  91.     $in =~ s/\'/\'\"\'\"\'/g;

  92.     return "'$in'";
  93. }


  94. #移除斜线号,用下划线取代
  95. # removeSlashes turns slashes into underscores for use as a file name.
  96. #

  97. sub removeSlashes
  98. {
  99.     local ($in) = @_;

  100. #将斜线替换成下划线
  101.     $in =~ s|/|_|g;

  102.     return "$in";
  103. }


  104. #
  105. # Usage
  106. #

  107. #输入格式错误时,提示使用方法
  108. sub Usage
  109. {
  110.     die("\nusage: $prog [:<number>] [-name <desktop-name>] [-depth <depth>]\n".
  111.         "                 [-geometry <width>x<height>]\n".
  112.         "                 [-pixelformat rgbNNN|bgrNNN]\n".
  113.         "                 <Xvnc-options>...\n\n".
  114.         "       $prog -kill <X-display>\n\n");
  115. }


  116. #
  117. # Kill
  118. #

  119. sub Kill
  120. {
  121. #转换格式,看句末注释
  122.     $opt{'-kill'} =~ s/(:\d+)\.\d+$/$1/; # e.g. turn :1.0 into :1

  123. #如果-kill参数值合法
  124.     if ($opt{'-kill'} =~ /^:\d+$/) {
  125. #将对应的pid文件路径赋给变量$pidFile
  126.                 $pidFile = "$vncUserDir/$host$opt{'-kill'}.pid";
  127.     } else {
  128. #如果-kill参数值不以$host:开头,退出并提示错误信息
  129.                 if ($opt{'-kill'} !~ /^$host:/) {
  130.                         die "\nCan't tell if $opt{'-kill'} is on $host\n".
  131.                         "Use -kill :<number> instead\n\n";
  132.                 }
  133. #将对应的pid文件路径赋给变量
  134.                 $pidFile = "$vncUserDir/$opt{'-kill'}.pid";
  135.     }
  136. #如果pid文件不可读,退出并提示错误信息
  137.     if (! -r $pidFile) {
  138.         die "\nCan't find file $pidFile\n".
  139.             "You'll have to kill the Xvnc process manually\n\n";
  140.     }
  141. #
  142.     $SIG{'HUP'} = 'IGNORE';
  143. #读出pid并去除末尾的回车符
  144.     chop($pid = `cat $pidFile`);
  145. #提示杀死Xvnc进行
  146.     warn "Killing Xvnc process ID $pid\n";
  147. #调用外部系统杀死进程
  148.     system("kill $pid");
  149. #删除进程文件
  150.     unlink $pidFile;
  151. #退出
  152.     exit;
  153. }


  154. #
  155. # ParseOptions takes a list of possible options and a boolean indicating
  156. # whether the option has a value following, and sets up an associative array
  157. # %opt of the values of the options given on the command line. It removes all
  158. # the arguments it uses from @ARGV and returns them in @optArgs.
  159. #
  160. #分析选项
  161. sub ParseOptions
  162. {
  163. #将模板里的参数读到数组@optval
  164.     local (@optval) = @_;
  165.        
  166. #定义局部变量$opt,数组@opts,@newargs,哈希表%valFollows
  167.     local ($opt, @opts, %valFollows, @newargs);

  168. #利用while循环取出数组中下标为单数的标量值作为哈希表的键,下标为双数的标量值作为哈希表的值
  169.     while (@optval) {
  170. #从左侧弹出下标为单数的标量值赋给变量$opt
  171.         $opt = shift(@optval);
  172. #将弹出的标量值从右侧弹入数组@opts
  173.         push(@opts,$opt);
  174. #从左侧弹出下标为双数的标量值赋给对应的哈希表的键
  175.         $valFollows{$opt} = shift(@optval);
  176.     }
  177. #定义空的数组和哈希表
  178.     @optArgs = ();
  179.     %opt = ();

  180. #利用while循环读取命令行参数
  181.     arg: while (defined($arg = shift(@ARGV))) {
  182. #利用foreach循环读取数组@opts中的值与命令行中对应的值
  183.                 foreach $opt (@opts) {
  184.                         if ($arg eq $opt) {
  185. #将命令行中的参数从右侧弹入数组@optArgs
  186.                                 push(@optArgs, $arg);
  187. #如果哈希表%valFollows中键的预设值不为0
  188.                                 if ($valFollows{$opt}) {
  189. #如果命令行中只输入了一个参数且不带参数值(如果两个参数连在一起,中间没有参数值怎么办?)
  190.                                         if (@ARGV == 0) {
  191. #提示使用方法
  192.                                                 &Usage();
  193.                                         }
  194. #将命令行中的参数值赋给哈希表%opt对应的键
  195.                                         $opt{$opt} = shift(@ARGV);
  196. #将哈希表中的值存入数组@optArgs中
  197.                                         push(@optArgs, $opt{$opt});
  198.                                 } else {
  199. #如果哈希表%valFollows中键的预设值为0
  200.                                         $opt{$opt} = 1;
  201.                                 }
  202. #读取下一个命令行参数
  203.                                 next arg;
  204.                         }
  205.                 }
  206. #将命令行中无法匹配模板的参数存入数组@newargs
  207.                 push(@newargs,$arg);
  208.     }
  209. #将没能匹配上的命令行参数重新赋给@ARGV
  210.     @ARGV = @newargs;
  211. }


  212. #例行检查,保证我们在一个可靠的环境中操作
  213. # Routine to make sure we're operating in a sane environment.
  214. #

  215. sub SanityCheck
  216. {
  217.         #定义本地变量,local相当于my
  218.     local ($cmd);

  219.     #下面的正则表达将获取程序的名字
  220.     # Get the program name
  221.     #
  222.         #"=~"叫做绑定操作符,绑定右侧的正则表达式与左侧的$0,默认的右侧正则表达式会与perl默认的变量$_进行匹配。
  223.         #m||,m是perl正则表达式(模式匹配)操作符的缩写match
  224.     ($prog) = ($0 =~ m|([^/]+)$|);

  225.     #检查环境变量PATH中包含我们所需要的命令
  226.     # Check we have all the commands we'll need on the path.
  227.     #

  228. cmd:
  229.         #foreach循环,每次取括号中的一个参数赋给$cmd
  230.     foreach $cmd ("uname","xauth","Xvnc","vncpasswd") {
  231.         #用split操作符将PATH环境变量通过符号":"拆分开,通过循环取出环境变量赋给$_,判断$_目录中的$cmd是否有可执行权限,$_是perl的默认变量
  232.                 for (split(/:/,$ENV{PATH})) {
  233.         #检查当前用户对$cmd命令是否具有可执行的权限
  234.                         if (-x "$_/$cmd") {
  235.         #如果找到了第一个可执行的$cmd,就检查下一个$cmd
  236.                         next cmd;
  237.                         }
  238.                 }
  239.         #如果遍历了PATH环境变量,找不到可执行的$cmd,则打印出没找到的$cmd并退出程序
  240.         #函数名:die
  241.         #调用语法:die (message);
  242.         #解说:终止程序并向STDERR输出错误信息。message可以为字符串或列表。如果最后一个参数不包含换行符,则程序文件名和行号也被输出。
  243.                 die "$prog: couldn't find \"$cmd\" on your PATH.\n";
  244.     }

  245.     #
  246.     # Check the HOME environment variable is set
  247.     #检查家目录环境变量已经设置好了

  248.         #如果查询发现家目录的环境变量没有定义,则打印出家目录环境变量没设置并退出程序
  249.     if (!defined($ENV{HOME})) {
  250.                 die "$prog: The HOME environment variable is not set.\n";
  251.     }
  252.         #改变目录到用户的家目录
  253.     chdir($ENV{HOME});

  254.     #
  255.     # Find socket constants. 'use Socket' is a perl5-ism, so we wrap it in an
  256.     # eval, and if it fails we try 'require "sys/socket.ph"'.  If this fails,
  257.     # we just guess at the values.  If you find perl moaning here, just
  258.     # hard-code the values of AF_INET and SOCK_STREAM.  You can find these out
  259.     # for your platform by looking in /usr/include/sys/socket.h and related
  260.     # files.
  261.     #

  262.         #获取操作系统的名字
  263.     chop($os = `uname`);
  264.         #获取操作系统的版本
  265.     chop($osrev = `uname -r`);

  266.         #执行perl目录下的Socket.pm查找AF_INET和SOCK_STREAM
  267.     eval 'use Socket';
  268.         # $@存储 Perl解释器从eval语句返回的错误消息,如果$@有内容的话,就接着查找sys/socket.ph
  269.     if ($@) {
  270.         #检查是否能够找到sys/socket.ph
  271.                 eval 'require "sys/socket.ph"';
  272.         #如果$@有内容的话,表示require失败
  273.                 if ($@) {
  274.         #通过判断操作系统是SunOS,如果版本是非4的话,hard-code AF_INET=2和SOCK_STREAM=2,如果版本是4的话,hard-code AF_INET=2和SOCK_STREAM=1
  275.                         if (($os eq "SunOS") && ($osrev !~ /^4/)) {
  276.                                 $AF_INET = 2;
  277.                                 $SOCK_STREAM = 2;
  278.                         } else {
  279.                                 $AF_INET = 2;
  280.                                 $SOCK_STREAM = 1;
  281.                         }
  282.         #如果require成功的话,就取sys/socket.ph里面的地址组和流套接字的值
  283.                 } else {
  284.                         $AF_INET = &AF_INET;
  285.                         $SOCK_STREAM = &SOCK_STREAM;
  286.                 }
  287.         #如果use Socket成功的话,就取Socket.pm里面的地址组和流套接字的值
  288.     } else {
  289.                 $AF_INET = &AF_INET;
  290.                 $SOCK_STREAM = &SOCK_STREAM;
  291.     }
  292. }
复制代码

论坛徽章:
0
3 [报告]
发表于 2013-03-05 13:31 |只看该作者
刚开始学习perl语言,借助别人优秀的程序提高自己的能力,如有错误,请帮忙指正~

论坛徽章:
46
15-16赛季CBA联赛之四川
日期:2018-03-27 11:59:132015年亚洲杯之沙特阿拉伯
日期:2015-04-11 17:31:45天蝎座
日期:2015-03-25 16:56:49双鱼座
日期:2015-03-25 16:56:30摩羯座
日期:2015-03-25 16:56:09巳蛇
日期:2015-03-25 16:55:30卯兔
日期:2015-03-25 16:54:29子鼠
日期:2015-03-25 16:53:59申猴
日期:2015-03-25 16:53:29寅虎
日期:2015-03-25 16:52:29羊年新春福章
日期:2015-03-25 16:51:212015亚冠之布里斯班狮吼
日期:2015-07-13 10:44:56
4 [报告]
发表于 2013-03-05 14:23 |只看该作者
这用中文把代码一行一行念出来,对写的人来说是一种磨炼因为要每一行每一个字符都看懂,但是对读的人来说没什么意义啊。

论坛徽章:
0
5 [报告]
发表于 2013-03-06 13:15 |只看该作者
回复 4# zhlong8


   因为我的工作中要用到unix中的vnc这个远程控制工具,但是很多人都对这个工具的运作过程不了解,我借助看这个工具的代码来学习perl,也正好拿出来让用vnc这个工具的人能了解一下它是怎么启动的,希望能帮到需要的人,呵呵。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP