HP OpenVMS Systems Documentation

Content starts here

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

检查这个例子时,注意以下几点:

  1. 第一次调用请求搜索 OpenVMS 簇系统中的所有节点。
  2. 第二次调用请求只处理其用户名开始于 M 或者是 SYSTEM 的进程。
  3. 第三次调用只选择那些其当前特权包括 SYSPRV (系统特权) 和 OPER (操作员) 并且可以有其他特权集的进程。
  4. 在标号 "loop" 和 "endloop" 之间的命令行不断地调用 F$PID 来获得满足 F$CONTEXT 调用设置的准则的进程。
  5. 在检索每个 PID 号之后,调用 F$GETJPI 返回在进程中运行的映象名。
  6. 最后,这个过程显示映象的名称。
  7. 在出错或 Ctrl/Y 操作的情况下,把控制传递给 error,并且如果有必要就关闭上下文。
  8. 注意,检查符号类型 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
   .
   .
   .


前页 后页 目录 索引