OpenVMS 用户手册
15.2.2 更改默认文件保护
您可能想要在命令过程中更改默认文件保护。以下命令过程在过程执行时更改建立文件的默认保护。该过程在终止之前恢复其原始的默认文件保护。
$ SAVE_PROT = F$ENVIRONMENT("PROTECTION")
$ SET PROTECTION = (SYSTEM:RWED,OWNER:RWED,GROUP,WORLD)/DEFAULT
.
.
.
$ SET PROTECTION=('SAVE_PROT')/DEFAULT
$ EXIT
|
注意,F$ENVIRONMENT 函数使用 SET PROTECTION
命令要求的语法返回默认保护代码。这让您对 SET PROTECTION 命令使用符号
SAVE_PROT 可恢复其原始的默认文件保护。15.3 获得有关系统的信息
您可以使用以下词法函数获得有关系统的信息:
F$CONTEXT
|
指定使用 F$PID 函数的选择准则。F$CONTEXT 函数允许 F$PID 函数获得有关任何 OpenVMS 簇系统节点上的进程信息。 |
F$CSID
|
返回一个 OpenVMS Cluster 标识号,并且更新指向系统的 OpenVMS Cluster
节点列表中当前位置的上下文符号。 |
F$GETQUI
|
返回以下有关信息:队列、当前在那些队列上的批量和打印作业、格式定义、和保持在系统作业队列文件中的特征定义。 |
F$GETSYI
|
返回有关您的本地系统或有关您的
OpenVMS 簇系统上的节点 (如果您的系统是 OpenVMS Cluster 的一部分) 的信息。
|
F$IDENTIFIER
|
把命名格式的标识符转换为数字格式,或者从数字格式转换为命名格式。
|
F$MESSAGE
|
返回与状态码关联的消息文本。 |
F$PID
|
返回允许您检查的进程的进程标识 (PID) 号。
|
F$TIME
|
返回当前日期和时间。
|
15.3.1 确定您的 OpenVMS 簇节点名
如果您的系统是 OpenVMS 簇环境的一部分,在此您可以注册到许多不同的节点,那么可以设置指出当前使用哪个节点的 DCL 提示。要做到这一点,把
F$GETSYI 函数包括在注册命令过程中以确定这个节点名。然后使用 SET PROMPT 命令设置对这个节点的唯一提示。
如果想要在提示字符串中只使用一部分节点名,那么使用 F$EXTRACT 函数抽取适当的字符。有关抽取字符的详情,请参阅
15.6.2 节。
在以下例子中,符号 NODE 定义为
FF$GETSYI("NODENAME"),然后把这个节点名用作提示:
$ NODE = F$GETSYI("NODENAME")
$ SET PROMPT = "''NODE'$ "
.
.
.
|
15.3.2 获得队列信息
您可以使用 F$GETQUI 函数获得有关批量和打印队列的许多类型的信息。要获得有关作业和队列中文件的信息,必须对这个作业有读存取、SYSPRV 特权或
OPER 特权。
以下例子展示如何确定批队列
VAX1_BATCH
是否处于停止状态。返回的值或是真或是假。如果这个队列不是处于停止状态,命令过程就可把作业提交给这个队列。
$ QSTOPPED = F$GETQUI("DISPLAY_QUEUE","QUEUE_STOPPED","VAX1_BATCH")
$ IF QSTOPPED THEN GOTO NOBATCH
$ SUBMIT/QUEUE=VAX1_BATCH TEST.COM
$ NOBATCH:
.
.
.
|
15.3.3 获得进程信息
您可以使用 F$PID
函数获得允许您检查的所有进程的进程标识 (PID)
号。您可以这样获得 PID 号:
- 如果有 WORLD 特权,可以检查系统上的所有进程
- 如果有 GROUP 特权,可以检查组上的所有进程
- 如果既没有 GROUP 也没有 WORLD
特权,只可以检查自己的进程
在获得 PID 号之后,您可以使用 F$GETJPI 函数获得进程的特定信息。
以下例子展示如何获得和显示允许您检查的进程的 PID 号:
$ ! Display the time when this procedure
$ ! begins executing
$ WRITE SYS$OUTPUT F$TIME()
$ !
$ CONTEXT = ""
$ START:
$ ! Obtain and display PID numbers until
$ ! F$PID returns a null string
$ !
$ PID = F$PID(CONTEXT)
$ IF PID .EQS. "" THEN EXIT
$ WRITE SYS$OUTPUT "Pid --- ''PID'"
$ GOTO START
|
系统使用符号 CONTEXT 保留指向的系统 PID
号列表的指针。每次循环时,系统更改指针找出该列表的下一个 PID
号。在显示所有 PID 号之后,就退出这个过程。
在以下例子中,过程显示每个进程的 PID 号和 UIC:
$ CONTEXT = ""
$ START:
$ ! Obtain and display PID numbers and UICs
$ !
$ PID = F$PID(CONTEXT)
$ IF PID .EQS. "" THEN EXIT
$ UIC = F$GETJPI(PID,"UIC")
$ WRITE SYS$OUTPUT "Pid --- ''PID' Uic--- ''UIC' "
$ GOTO START
|
注意,把
F$GETJPI 函数包括在 WRITE 命令中,可以缩短这个命令过程,如下所示:
$ CONTEXT = ""
$ START:
$ PID = F$PID(CONTEXT)
$ IF PID .EQS. "" THEN EXIT
$ WRITE SYS$OUTPUT "Pid --- ''PID' Uic --- ''F$GETJPI(PID,"UIC")'"
$ GOTO START
|
15.3.4 F$CONTEXT 词法函数
要获得 OpenVMS 簇系统任何节点上的进程信息,使用 F$CONTEXT 函数。
在以下例子中,调用 F$CONTEXT 三次来设置选择准则:
$!Establish an error and Ctrl/Y handler
$!
$ ON ERROR THEN GOTO error
$ ON CONTROL_Y THEN GOTO error
$!
$ ctx = ""
$ temp = F$CONTEXT ("PROCESS", ctx, "NODENAME", "*","EQL") (1)
$ temp = F$CONTEXT ("PROCESS", ctx, "USERNAME", "M*,SYSTEM","EQL") (2)
$ temp = F$CONTEXT ("PROCESS", ctx, "CURPRIV", "SYSPRV,OPER", "ALL") (3)
$!
$!Loop over all processes that meet the selection criteria.
$!Print the PID number and the name of the image for each process.
$!
$loop: (4)
$ pid = F$PID(ctx)
$ IF pid .EQS. ""
$ THEN
$ GOTO endloop
$ ELSE
$ image = F$GETJPI(pid,"IMAGNAME") (5)
$ SHOW SYMBOL pid
$ WRITE SYS$OUTPUT image (6)
$ GOTO loop
$ ENDIF
$!The loop over the processes has ended.
$!
$endloop:
$!
$ EXIT
$!
$!Error handler. Clean up the context's memory with
$!the CANCEL selection item keyword.
$!
$error:
$ IF F$TYPE(ctx) .eqs. "PROCESS_CONTEXT" THEN - (7)
-$ temp = F$CONTEXT ("PROCESS", ctx, "CANCEL") (8)
$!
$ EXIT
|
检查这个例子时,注意以下几点:
- 第一次调用请求搜索 OpenVMS 簇系统中的所有节点。
- 第二次调用请求只处理其用户名开始于 M 或者是 SYSTEM 的进程。
- 第三次调用只选择那些其当前特权包括 SYSPRV (系统特权) 和 OPER (操作员) 并且可以有其他特权集的进程。
- 在标号
"loop" 和 "endloop" 之间的命令行不断地调用 F$PID 来获得满足 F$CONTEXT
调用设置的准则的进程。
- 在检索每个 PID
号之后,调用 F$GETJPI 返回在进程中运行的映象名。
- 最后,这个过程显示映象的名称。
- 在出错或 Ctrl/Y 操作的情况下,把控制传递给 error,并且如果有必要就关闭上下文。
- 注意,检查符号类型
PROCESS_CONTEXT。如果这个符号有这个类型,必须调用 F$CONTEXT
来取消选择准则。如果这个符号不是类型
PROCESS_CONTEXT,就没有在 F$CONTEXT
中设置选择准则,或者这个符号与 F$PID
一起使用,直到出错或者直至到达进程列表的末端。
15.4 获得有关文件和设备的信息
您可以使用以下词法函数获得文件和设备的信息:
F$DEVICE
|
返回系统上符合指定选择准则的所有设备的设备名 |
F$FILE_ATTRIBUTES
|
返回文件属性的信息 |
F$GETDVI
|
返回指定设备的信息 |
F$PARSE
|
分析文件说明,并且返回请求的一个字段或多个字段 |
F$SEARCH
|
为查找文件搜索目录
|
15.4.1 搜索设备
要使用系统服务 $GETDVI
获得特定设备的信息,您必须提供设备名给这个服务。如果不知道设备名,可以使用词法函数 F$DEVICE 查找。
F$DEVICE
函数允许基于设备名、设备种类或设备类型的通配符搜索。要基于设备类型搜索,您也必须指定设备种类。
您可以在命令过程的循环中使用 F$DEVICE 函数返回匹配指定选择准则的设备名。每次执行 F$DEVICE 函数时,它返回系统上匹配选择准则的下一个设备。注意,不是按特定次序返回设备。在返回最后一个设备名之后,下一个 F$DEVICE 函数调用返回空串。
这个命令过程显示在单元 0 上所有 RA60 设备的设备名:
$ START:
$ DEVICE_NAME = F$DEVICE("*0:","DISK","RA60")
$ IF DEVICE_NAME .EQS. "" THEN EXIT
$ SHOW SYMBOL DEVICE_NAME
$ GOTO START
|
15.4.2 搜索目录中的文件
在处理文件之前,命令过程应该使用 F$SEARCH 函数测试文件是否存在。例如,以下命令过程使用 F$PARSE 把一个设备和目录字符串应用于文件 STATS.DAT。然后,该过程使用 F$SEARCH 函数确定 STATS.DAT 是否出现在 DISK3:[JONES.WORK]
中。如果是,那么该命令过程处理这个文件。否则,该命令过程提示输入另一个文件。
$ FILE = F$PARSE("STATS.DAT","DISK3:[JONES.WORK]",,,"SYNTAX_ONLY")
$ IF F$SEARCH(FILE) .EQS. "" THEN GOTO GET_FILE
$ PROCESS_FILE:
.
.
.
$ GET_FILE:
$ INQUIRE FILE "File name"
$ GOTO PROCESS_FILE
|
在确定文件存在之后,该过程可以使用 F$PARSE
或 F$FILE_ATTRIBUTES 函数获得这个文件的附加信息。例如:
$ IF F$SEARCH("STATS.DAT") .EQS. "" THEN GOTO GET_FILE
$ PROCESS_FILE:
$ NAME = F$PARSE("STATS.DAT",, "NAME")
.
.
.
$ GET_FILE:
$ INQUIRE FILE "File name"
$ GOTO PROCESS_FILE
|
15.4.3 删除文件的旧版本
如果命令过程建立了一个在过程终止后不再需要的文件,那么在退出过程之前删除或清除这些文件。使用 PURGE 命令可删除文件的除最新一个之外所有版本。使用带版本号的 DELETE 命令可删除文件的特定版本,或者在版本字段使用通配符可删除文件的所有版本。 在命令过程中使用 DELETE
命令时如要避免出错消息,可使用 F$SEARCH
函数先验证文件存在然后删除之。例如,您可以编写一个命令过程,只当某些模块执行时才建立文件 TEMP.DAT。以下命令行只当 TEMP.DAT 存在时才发出 DELETE 命令:
$ IF F$SEARCH("TEMP.DAT") .NES. "" THEN DELETE TEMP.DAT;*
|
15.5 翻译逻辑名
您可以使用以下词法函数翻译逻辑名:
F$LOGICAL
|
返回逻辑名的等价串。
|
F$TRNLNM
|
返回逻辑名的等价串或请求的属性。 |
注意
F$TRNLNM 函数取代 OpenVMS 操作系统初期版本使用的 F$LOGICAL
函数。您应该使用
F$TRNLNM (代替 F$LOGICAL)
来确保命令过程使用当前系统技术来处理逻辑名。 |
有些情形下,您可能想要在命令过程中使用逻辑名而不是符号作为变量。程序存取逻辑名比存取 DCL
符号更容易。因此,要把信息传递给从命令过程运行的程序,可使用符号获得信息。然后使用 DEFINE 或 ASSIGN
命令使符号的值等同于一个逻辑名。
您也可以使用 F$TRNLNM
函数确定逻辑名的值,然后把这个值赋予一个符号。
以下例子测试逻辑名 NAMES 是否已被定义。如果已定义,那么过程运行 PAYROLL.EXE。否则,过程获得符号 FILE 的值,并且使用这个值来建立逻辑名 NAMES。PAYROLL.EXE 使用逻辑名 NAMES
引用雇员名的文件。
$ ! Make sure that NAMES is defined
$ IF F$TRNLNM("NAMES") .NES. "" THEN GOTO ALL_SET
$ INQUIRE FILE "File with employee names"
$ DEFINE NAMES 'FILE'
$ !
$ ! Run PAYROLL, using the file indicated by NAMES
$ ALL_SET:
$ RUN PAYROLL
.
.
.
|
这个命令过程定义在程序 PAYROLL 中使用的逻辑名:
$ DEFINE NAMES DISK4:[JONES]EMPLOYEE_NAMES.DAT
$ RUN PAYROLL
.
.
.
$ WRITE SYS$OUTPUT "Finished processing ",F$TRNLNM("NAMES")
|
在这个过程的末端,WRITE 命令显示一条消息指出文件已被处理。15.6 处理字符串
您可以使用以下词法函数处理字符串:
F$CVTIME
|
返回时间字符串的信息 |
F$EDIT
|
编辑字符串
|
F$ELEMENT
|
从其元素被定界符分隔的字符串中抽取元素 |
F$EXTRACT
|
抽取一段字符串
|
F$FAO
|
格式化输出字符串 |
F$LENGTH
|
确定字符串的长度 |
F$LOCATE
|
在字符串中找出一个字符或子串,并返回其偏移
|
15.6.1 确定字符串或字符是否出现
检查字符串的一个普通原因是确定一个字符 (或子串) 是否出现在字符串中。要做到这一点,使用 F$LENGTH 和 F$LOCATE 函数。如果 F$LOCATE
函数返回的值等于
F$LENGTH 函数返回的值,那么要寻找的字符不出现。
以下过程需要一个包括版本号的文件名。要确定是否出现一个版本号,该过程测试在文件名的版本号之前分号 (;) 是否包括在用户输入的文件名中。
$ INQUIRE FILE "Enter file (include version number)"
$ IF F$LOCATE(";", FILE) .EQ. F$LENGTH(FILE) THEN -
GOTO NO_VERSION
.
.
.
|
F$LOCATE 函数返回分号的偏移。偏移开始于 0;因而,如果分号是字符串中的首位字符,F$LOCATE 函数将返回整数 0。如果分号不出现在字符串中,那么 F$LOCATE 函数返回一个偏移,它等于字符串中的最后一个字符的偏移加 1。这个值与 F$LENGTH
返回的长度一样,它度量从数 1 开始的字符串长度。15.6.2 抽取部分字符串
要抽取一部分字符串,使用 F$EXTRACT 函数或 F$ELEMENT 函数。使用 F$EXTRACT
函数抽取开始于已定义偏移的子串。使用 F$ELEMENT
函数抽取在两个定界符之间的部分字符串。要使用这些函数中的任意一个,必须知道要分析字符串的一般格式。注意,不需要使用 F$EXTRACT 或 F$ELEMENT
分析文件说明或时间字符串。作为代替,使用 F$PARSE 或
F$CVTIME 抽取文件说明或时间字符串的要求部分。
您也可以在抽取的同时确定组名的长度。
如果一个字符串包含分隔该字符串不同部分的定界符,可使用 F$ELEMENT
函数抽取您想要的部分。从字符串中抽取在逗号之间的部分,可以使用 F$ELEMENT 获得不同类型的存取权。要确定系统存取权,获得第一个元素;要确定拥有者存取权,获得第二个元素;以此类推。注意,使用 F$ELEMENT
函数时,元素号码开始于零。基于这个原因,使用整数 3 指定第 4 个元素。
以下命令过程使用 F$EXTRACT 函数抽取 UIC
的组部分。这允许过程执行不同集合的命令,视用户的 UIC
组定。
$ UIC = F$USER()
$ GROUP_LEN = F$LOCATE(",",UIC) - 1
$ GROUP = F$EXTRACT(1,GROUP_LEN,UIC)
$ GOTO 'GROUP'_SECTION
.
.
.
$ WRITERS_SECTION:
.
.
.
$ MANAGERS_SECTION:
.
.
.
|
首先,过程使用 F$USER 函数确定 UIC。然后,该过程使用 F$LOCATE
找出逗号的偏移确定组名长度。逗号把组从 UIC 用户部分分隔开来。在左中括号和逗号之间的任何字符是组名部分。例如,来自
UIC [WRITERS,SMITH] 的组名是 WRITERS。
在确定长度之后,该过程使用 F$EXTRACT 函数抽取组名。组名开始于偏移 1 并结束于在逗号之前的字符。最后,该过程直接执行到适当的标号。
以下例子展示如何在抽取的同时确定组名的长度:
$ UIC = F$USER()
$ GROUP = F$EXTRACT(1,F$LOCATE(",",UIC) - 1, UIC)
$ GOTO 'GROUP'_SECTION
|
以下例子展示如何用逗号分隔保护码中的每个存取类型:
$ PROT = F$ENVIRONMENT("PROTECTION")
$ SHOW SYMBOL PROT
PROT = "SYSTEM=RWED, OWNER=RWED, GROUP=RE, WORLD"
|
在这个例子中的命令从默认保护码中抽取全体用户存取部分 (第 4 个元素):
$ PROT = F$ENVIRONMENT("PROTECTION")
$ WORLD_PROT = F$ELEMENT(3,",",PROT)
.
.
.
|
F$ELEMENT 函数返回在第三逗号和字符串末端之间的每个字符。因而,如果您的默认保护允许全体用户的读存取,那么将返回字符串 "WORLD=R"。
在获得全体用户存取字符串之后,可能需要进一步检查它。例如:
$ PROT = F$ENVIRONMENT("PROTECTION")
$ WORLD_PROT = F$ELEMENT(3,",",PROT)
$ IF F$LOCATE("=", WORLD_PROT) .EQ. F$LENGTH(WORLD_PROT) -
THEN GOTO NO_WORLD_ACCESS
.
.
.
|
|