当然,除非可以与整个系统交互,否则脚本的用处不大。下面是一些允许脚本与系统交互的内置函数:
|
脚本与较大系统交互的最简单方式就是使用 "run" 函数:它获取要运行的命令,并将该命令的输出作为字符串返回。例如:
dory:> configuration version script dump(run('get boot_time')) ' boot_time = 2009-10-12 07:02:17\n'
内置的 dump 函数转储参数,但不展开任何嵌入的换行符。ECMAScript 的字符串处理工具可用于拆分输出。例如,按空格拆分上面的结果:
dory:> configuration version script dump(run('get boot_time').split(/\s+/)) ['', 'boot_time', '=', '2009-10-12', '07:02:17', '']
run 函数非常强大,它往往专门依靠解析输出来获取有关系统的信息-但是这显然存在缺陷,因为它让脚本解析用户可读的输出,输出在将来可能会发生更改,也可能不会。要更稳妥地收集有关系统的信息,请使用内置的 "get" 函数。对于 boot_time 属性,此函数返回的内容不是字符串,而是 ECMAScript Date 对象,以允许通过编程方式处理属性值。例如,您可能希望结合使用 boot_time 属性和当前时间确定自引导以来经过的时间:
script run('configuration version'); now = new Date(); uptime = (now.valueOf() - get('boot_time').valueOf()) / 1000; printf('up %d day%s, %d hour%s, %d minute%s, %d second%s\n', d = uptime / 86400, d < 1 || d >= 2 ? 's' : '', h = (uptime / 3600) % 24, h < 1 || h >= 2 ? 's': '', m = (uptime / 60) % 60, m < 1 || m >= 2 ? 's': '', s = uptime % 60, s < 1 || s >= 2 ? 's': '');
假设上面的内容保存为 "uptime.aksh",则可以通过以下方式运行:
% ssh root@dory < uptime.aksh Pseudo-terminal will not be allocated because stdin is not a terminal. Password: up 2 days, 10 hours, 47 minutes, 48 seconds
由于是 ssh 客户机,因此会出现有关伪终端分配的消息;该消息所指的问题可以通过为 ssh 指定 "-T" 选项进行处理。
在具有动态子代的上下文中,以编程方式迭代这些子代可能非常有用。这可以使用 list 函数实现,该函数返回动态子代数组。例如,下面是迭代每个项目中每个共享资源的脚本,输出所用空间和可用空间:
script run('shares'); projects = list(); for (i = 0; i < projects.length; i++) { run('select ' + projects[i]); shares = list(); for (j = 0; j < shares.length; j++) { run('select ' + shares[j]); printf("%s/%s %1.64g %1.64g\n", projects[i], shares[j], get('space_data'), get('space_available')); run('cd ..'); } run('cd ..'); }
下面是运行该脚本的输出(假设将其保存到名为 "space.aksh" 的文件中):
% ssh root@koi < space.aksh Password: admin/accounts 18432 266617007104 admin/exports 18432 266617007104 admin/primary 18432 266617007104 admin/traffic 18432 266617007104 admin/workflow 18432 266617007104 aleventhal/hw_eng 18432 266617007104 bcantrill/analytx 1073964032 266617007104 bgregg/dashbd 18432 266617007104 bgregg/filesys01 26112 107374156288 bpijewski/access_ctrl 18432 266617007104 ...
如果有人希望获得以上结果的 "易于阅读"(虽然通过编程方式比较难处理)版本,则可以直接解析 get 命令的输出:
script run('shares'); projects = list(); printf('%-40s %-10s %-10s\n', 'SHARE', 'USED', 'AVAILABLE'); for (i = 0; i < projects.length; i++) { run('select ' + projects[i]); shares = list(); for (j = 0; j < shares.length; j++) { run('select ' + shares[j]); share = projects[i] + '/' + shares[j]; used = run('get space_data').split(/\s+/)[3]; avail = run('get space_available').split(/\s+/)[3]; printf('%-40s %-10s %-10s\n', share, used, avail); run('cd ..'); } run('cd ..'); }
以下是运行该新脚本的部分输出(假设将其命名为 "prettyspace.aksh"):
% ssh root@koi < prettyspace.aksh Password: SHARE USED AVAILABLE admin/accounts 18K 248G admin/exports 18K 248G admin/primary 18K 248G admin/traffic 18K 248G admin/workflow 18K 248G aleventhal/hw_eng 18K 248G bcantrill/analytx 1.00G 248G bgregg/dashbd 18K 248G bgregg/filesys01 25.5K 100G bpijewski/access_ctrl 18K 248G ...
即使是在具有静态子代的上下文中,以编程方式迭代这些子代同样非常有用。这可以使用 children 函数实现,该函数返回静态子代数组。例如,下面是迭代每个服务的脚本,输出服务的状态:
configuration services script var svcs = children(); for (var i = 0; i < svcs.length; ++i) { run(svcs[i]); try { printf("%-10s %s\n", svcs[i], get('<status>')); } catch (err) { } run("done"); }
下面是运行该脚本的输出(假设将其保存到名为 "svcinfo.aksh" 的文件中):
% ssh root@koi < space.aksh Password: cifs disabled dns online ftp disabled http disabled identity online idmap online ipmp online iscsi online ldap disabled ndmp online nfs online nis online ntp online scrk online sftp disabled smtp online snmp disabled ssh online tags online vscan disabled
Choices 函数将返回一组值已知且可枚举的任何属性的有效属性值数组。例如,以下脚本将使用 choices 函数检索共享资源节点上所有池的列表,然后迭代所有池来列出项目和共享资源以及可用空间。
fmt = '%-40s %-15s %-15s\n'; printf(fmt, 'SHARE', 'USED', 'AVAILABLE'); run('cd /'); run('shares'); pools = choices('pool'); for (p = 0; p < pools.length; p++) { set('pool', pools[p]); projects = list(); for (i = 0; i < projects.length; i++) { run('select ' + projects[i]); shares = list(); for (j = 0; j < shares.length; j++) { run('select ' + shares[j]); share = pools[p] + ':' + projects[i] + '/' + shares[j]; printf(fmt, share, get('space_data'), get('space_available')); run('cd ..'); } run('cd ..'); } }
以下是运行该脚本的输出:
SHARE USED AVAILABLE pond:projectA/fs1 31744 566196178944 pond:projectA/fs2 31744 566196178944 pond:projectB/lun1 21474836480 587670999040 puddle:deptA/share1 238475 467539219283 puddle:deptB/share1 129564 467539219283 puddle:deptB/share2 19283747 467539219283