OpenVMS 用户手册
14.20.2 使用 PIPE 命令执行流水线
流水线是一串用管道连接的流水线段命令,以垂直条 (|)
分隔符表示。流水线段命令是出现在流水线中的 DCL 命令。管道把一个流水线段命令的 SYS$OUTPUT 连接到下一个命令的
SYS$INPUT。流水线的格式如下所示:
PIPE pipeline-segment-command | pipeline-segment-command [|...]
|
每个流水线段命令在一个单独子进程中运行,它的
SYS$OUTPUT 连接到下一个流水线段命令的 SYS$INPUT。这些子进程并行执行;然而,它们同步到这种程度:除第一个之外,每个流水线段命令读取上一个的标准输出作为它的标准输入。当最后一个流水线段命令完成时,流水线就执行完成。
在流水线中使用 "筛选应用程序" 是很普通的。筛选应用程序是这样一个程序,它从 SYS$INPUT 获取数据,按特定方法改变它,然后把它写入 SYS$OUTPUT。
DCL 函数有些方面会在流水线的上下文中有所不同。例如:
- 使用 SYS$COMMAND
子进程的 SYS$COMMAND 通常与它的 SYS$INPUT 一样 (如果不包括任何命令过程)。然而,在流水线中,子进程的 SYS$COMMAND 被设置为父进程的 SYS$COMMAND,而不是上面的管道 (它是流水线段命令的 SYS$INPUT)。
- 文件存取方法
流水线段命令只可以使用
RMS 顺序文件存取方法读取和写入管道。某些 OpenVMS
公用程序可能不是使用顺序存取的方法存取它们的输入和输出文件。这些操作在流水线中是不被支持而会失败,如以下例子:
$ PIPE CC/NOOBJ/NOLIS TEST.C | SEARCH SYS$INPUT/WIND=(1,1) "%cc-w-"
%SEARCH-F-RFAERR, RMS error using RFA access
-RMS-F-RAC, invalid record access mode
|
在这个例子中,SEARCH 命令的 /WINDOW 限定词需要相对文件存取方法。 - 符号替换
注意 DCL
翻译符号的次序。符号替换发生在命令处理的第一阶段。如果把一个符号定义为 PIPE 命令的一部分,那么在执行这个符号实际定义的命令之前,DCL 尝试翻译这个符号。使用和号 (&) 可推迟符号替换。有关详情,请参阅
12.12.2 节。 - 使用 SYS$PIPE
在多数情况下,来自管道的输入可以通过读取 SYS$INPUT 的数据获得。然而,当命令过程被调用为流水线段命令时,SYS$INPUT
重定向到这个命令过程文件。要在命令过程内部从管道获得数据,可以使用逻辑名 SYS$PIPE。 以下是一个流水线 DCL 应用程序 TEE.COM
的例子:
$ ! TEE.COM - command procedure to display/log data flowing through
$ ! a pipeline
$ ! Usage: @TEE log-file
$
$ OPEN/WRITE tee_file 'P1'
$ LOOP:
$ READ/END_OF_FILE=EXIT SYS$PIPE LINE
$ WRITE SYS$OUTPUT LINE ! Send it out to the next stage of the pipeline
$ WRITE tee_file LINE ! Log output to the log file
$ GOTO LOOP
$ EXIT:
$ CLOSE tee_file
$ EXIT
|
要使用 TEE.COM,输入以下 PIPE 命令:
$ PIPE SHOW SYSTEM | @TEE showsys.log | SEARCH SYS$INPUT LEF
|
命令过程 TEE.COM 用来记录通过流水线的数据流。它从 SYS$PIPE 读入数据,而不是
SYS$INPUT。 - 映象校验
按照默认,在流水线中映象校验被停掉,即使在输入 PIPE 命令之前执行了命令 SET
VERIFY=IMAGE。这阻止数据记录的副本通过流水线。 要在流水线中启动映象校验,必须在流水线段命令之前执行显式的 SET VERIFY=IMAGE 命令。可以使用一个子外壳做到这一点,如下所示:
$ PIPE ... | (SET VERIFY=IMAGE ; ...) | ...
|
14.20.3 使用 PIPE 命令执行子外壳
子外壳是一个或多个用分隔符分隔的命令序列,并且括入圆括号中。子外壳的格式如下所示:
PIPE ( command-sequence [separator command-sequence]... )
|
子外壳的命令序列在子进程环境中执行。在执行下一个命令序列之前,DCL 等待子外壳完成。( ) 分隔符类似于
SPAWN/WAIT 命令。
按这个格式使用 PIPE 命令时,要小心地处理符号替换。在定义符号后,在以后引用这个符号之前使用和号 (&)
延迟符号替换。否则符号替换将发生在命令处理的第一阶段期间,而在这个时间符号定义是不可靠的。14.20.4 使用 PIPE 命令执行后台程序
使用以下格式,命令序列可以在子进程环境中执行:
PIPE command-sequence [ separator
command-sequence]... &
|
DCL 不等待命令序列完成。一旦建立后台子进程,就把控制传递回 DCL。
14.20.5 使用 PIPE 命令重定向输入/输出
在命令执行期间,命令序列可以把它的 SYS$INPUT、SYS$OUTPUT 或 SYS$ERROR
重定向到一个文件,如下所示:
- 要重定向 SYS$INPUT:
PIPE command-sequence < redirected-input-file
|
- 要重定向 SYS$OUTPUT:
PIPE command-sequence > redirected-output-file
|
- 要重定向 SYS$ERROR:
PIPE command-sequence 2> redirected-error-file
|
流水线段命令也可以重定向它的 SYS$INPUT、SYS$OUTPUT 或 SYS$ERROR。然而,只允许最后一个流水线段命令重定向 SYS$OUTPUT,并且只允许第一个流水线段命令重定向 SYS$INPUT。
注意,PIPE 命令重定向不同于使用 DEFINE 或 ASSIGN
命令建立的重定向。其差别如下:
- 重定向是在监督程序模式下建立。这意味着用户模式应用程序和 DCL 命令两个都受到这个重定向的影响。
- 重定向环境只应用于指定重定向语法的命令序列或流水线段命令。在这个命令序列或流水线段命令执行后,其原始进程输入/输出环境 (例如,SYS$INPUT、SYS$OUTPUT 和 SYS$ERROR)
在命令继续执行之前恢复。
当 SYS$OUTPUT 重定向时,总是建立重定向的输出文件,而不管命令序列是否实际上写入
SYS$OUTPUT。如果已经存在与重定向输出文件同名的文件版本,那么就建立这个文件的新版本。(这个行为与在监督程序模式下使用 DEFINE 或 ASSIGN 命令重新定义 SYS$OUTPUT
一样。)
注意,重定向的文件在这个命令序列执行之前就已建立。如果重定向的文件也在这个命令顺序中使用,那么操作可能失败,如以下例子所示:
$ PIPE SEARCH TRANS.LOG "alpha" > TRANS.LOG
%SEARCH-W-OPENIN, error opening TRANS.LOG;2 as input
-RMS-E-FLK, file currently locked by another user
|
在这个例子中,新版本的 TRANS.LOG
已建立,并且打开供写存取;然后,SEARCH 命令尝试读取 TRANS.LOG 的最新版本,而不是期望的上一个版本。
当 SYS$ERROR 被重定向时,重定向的出错文件只当命令序列在执行期间实际写入 SYS$ERROR 时才建立,并且没有现有文件与重定向的出错文件同名。如果与重定向出错文件同名的文件已经存在,那么这个文件就被打开为重定向的出错文件。然后,这个命令序列产生的出错输出被附加到重定向出错文件的末端。(这个行为与在监督程序模式下使用 DEFINE 或 ASSIGN 命令重新定义 SYS$OUTPUT 一样。)
14.20.6 中断 PIPE 命令
按下 Ctrl/Y,可以中断 PIPE 命令。如果 PIPE
命令正在流水线或子外壳命令序列中执行,这个命令序列和 PIPE
命令就会被删除。在这种情况下,立即在中断后输入
CONTINUE 命令将不会恢复 PIPE 命令的执行。
如果 PIPE 命令正在执行一个命令序列,而不是子外壳或流水线命令序列,那么 DCL 这时对这个命令序列的处理就象一个不带 PIPE 命令动词的 DCL 命令,并且被 Ctrl/Y 中断。有关 Ctrl/Y 中断的详情,请参阅
13.11 节。14.20.7 改进子进程的操作性能
在执行期间,PIPE
命令可以产生许多子进程。通常,被命令序列调用的应用程序不依赖于进程逻辑名和符号名。在这种情况下,使用 /NOLOGICAL_NAMES
和 /NOSYMBOLS
限定词可以加速子进程的派生,它们抑制把进程逻辑名和符号传递给 PIPE 命令建立的子进程。
以下例子使用 PIPE 命令:
- 下例展示两个使用多个命令的简单方法,在命令过程中通过符号定义建立有用工具:
$ CD_WORK :== PIPE SAVE_DIR=F$DIRECTORY() ; SET DEFAULT FOO:[WORK]
$ BACK :== SET DEF 'SAVE_DIR'
$
$ CD_WORK ! Switch to working directory
$ :
$ :
$ BACK ! Switch back to home directory
$ GET_RECORD :== PIPE READ/END_OF_FILE=CLEANUP IN RECORD ; -
F$EDIT(RECORD, "COMPRESS, TRIM")
$
$ OPEN IN EMPLOYEE.DAT
$ LOOP:
$ GET_RECORD
$ :
$ :
$ GOTO LOOP
$
$ CLEAN_UP:
$ :
|
- 下例展示编译和链接操作。注意,如果编译没有任何出错,目标文件被链接产生一个可执行映象。如果程序编译出错,那么跳过链接步。
$ PIPE cc foo.c && link foo, sys$library:vaxcrtl.olb/lib
|
- 下例展示如何使用执行条件命令在命令过程中设置简单出错处理控制流。注意,如果映象 COLLECT_DATA 失败,控制指引到 CLEAN_UP。
$ PIPE RUN COLLECT_DATA.EXE || GOTO CLEAN_UP
$ :
$ :
$ EXIT
$
$ CLEAN_UP:
$ :
$ :
|
- 在这个例子中,PIPE 命令建立后台进程处理复制大文件。
$ PIPE COPY LARGE_FILE.DAT REMOTE"user password"::[DESTINATION]*.* &
|
- 下例展示如何设置在子进程中完成的子外壳命令序列。结果,对进程特定特征 (例如,默认目录) 的更改在子外壳完成后将不影响当前进程。注意,保存集恢复到一个子目录中,为运行程序 FOO 提供必要的数据。
$ PIPE (SET DEF [.DATA_DIR] ; BACKUP DATA.SAV/SAV [...]) ; RUN FOO
|
- 下例在一个命令中使用流水线功能标识系统上的所有睡眠进程:
$ PIPE SHOW SYSTEM | SEARCH SYS$INPUT HIB
|
- 下例在单个命令中使用流水线功能运行一个测试、排序结果,并且把结果与基准文件进行比较,而不必产生中间文件:
$ PIPE RUN TEST | SORT/SPECIFICATION=TEST.SRT SYS$INPUT SYS$OUTPUT -
| DIFF SYS$INPUT TEST.BENCHMARK
|
- 下例展示一个在流水线中把子外壳指定为管道段命令的方法:
$ PIPE ( SET DEF WRK$:[WORK] ; RUN REPORT ) | MAIL SYS$INPUT SMITH
|
- 下例展示在流水线中使用 /PAGE 限定词。/PAGE 功能也存在于许多其他 DCL 命令中,并且同样可以与 PIPE 命令一起使用,以形成其他有用的工具
。
$ more :== TYPE/PAGE=SAVE SYS$INPUT
$ PIPE ANA/RMS PAGE.TXT | more
Check RMS File Integrity 26-JAN-2002 16:12:00.06 Page 1
SYS$SYSDEVICE:[TEST]PAGE.TXT;2
FILE HEADER
File Spec: SYS$SYSDEVICE:[TEST]PAGE.TXT;2
File ID: (4135,58220,0)
Owner UIC: [PIPE]
Protection: System: RWED, Owner: RWED, Group: RE, World:
Creation Date: 26-NOV-2002 16:08:50.05
Revision Date: 26-NOV-2002 16:09:09.06, Number: 1
Expiration Date: none specified
Backup Date: none posted
Contiguity Options: none
Performance Options: none
Reliability Options: none
Journaling Enabled: none
RMS FILE ATTRIBUTES
RETURN/SPACE=More, PREV/NEXT=Scroll, INS/REM=Pan, SELECT=80/132, Q=Quit
|
第 15 章 使用词法函数获得并处理信息
词法函数返回信息给命令行或命令过程。返回的信息可以涉及进程、系统、文件和设备、逻辑名、字符串或数据类型。词法函数用前缀 F$ 标识。
通常可以在应用符号或表达式的上下文中使用词法函数。在命令过程中,您可以使用词法函数翻译逻辑名、执行字符串处理以及确定过程的当前处理模式。许多词法函数返回的信息也可以从 DCL 命令
获得。
本章包括的信息涉及:
- 词法函数如何起作用
- 获得有关进程的信息
- 获得有关系统的信息
- 获得有关文件和设备的信息
- 翻译逻辑名
- 处理字符串
- 处理数据类型
有关词法函数的详情,请参阅联机求助。有关本章论述的命令详情,请参阅 OpenVMS DCL Dictionary。15.1 为什么要使用词法函数
如果是从词法函数而不是从命令获得信息,那么在命令过程中更容易处理。例如,您可以使用 F$ENVIRONMENT 函数或 SHOW
DEFAULT 命令获得当前默认目录的名称。其差别如下:
- 如果使用 F$ENVIRONMENT
函数,可以把结果赋值给一个符号,以后在这个过程中可以使用这个符号。例如:
$ DIR_NAME = F$ENVIRONMENT("DEFAULT")
$ SET DEFAULT DISK4:[TEST]
.
.
.
$ SET DEFAULT 'DIR_NAME'
|
F$ENVIRONMENT 函数返回当前默认磁盘和目录,并且把这个值存储到符号 DIR_NAME。在过程的末端,SET DEFAULT 命令使用符号 DIR_NAME 恢复其默认值。
- 如果使用 SHOW DEFAULT 命令代替 F$ENVIRONMENT
词法函数获得当前默认目录的值,就不能把这个输出直接赋值给一个符号。作为代替,该过程如下:
$! Redirect the output of the SHOW DEFAULT command to a file.
$ DEFINE/SUPERVISOR_MODE SYS$OUTPUT DISK4:[TEST]TEMPFILE.DAT
$ SHOW DEFAULT
$ DEASSIGN SYS$OUTPUT
$!
$ OPEN/READ DIR_FILE DISK4:[TEST]TEMPFILE.DAT ! Open the file.
$ READ DIR_FILE DIR_NAME, ! Read the file.
$ SET DEFAULT 'DIR_NAME' ! Reset the directory.
$ CLOSE DIR_FILE ! Close the file.
$ DELETE DISK4:[TEST]TEMPFILE.DAT;* ! Delete the file.
|
15.2 获得有关进程的信息
在命令过程中经常需要更改进程特征,然后使之恢复。您可以使用以下词法函数获得进程信息:
F$DIRECTORY
|
返回当前默认目录字符串。
|
F$ENVIRONMENT
|
返回进程的命令环境的信息。
|
F$GETJPI
|
返回有关您的进程或系统上的其他进程的计帐、状态和标识信息。 |
F$MODE
|
展示进程执行的模式。
|
F$PRIVILEGE
|
指出进程是否有指定特权。
|
F$PROCESS
|
返回进程的名称。
|
F$SETPRV
|
设置指定特权。这个函数也指出指定特权是否在使用这个
F$SETPRV 函数之前允许。 |
F$USER
|
返回用户标识码 (UIC)。 |
F$VERIFY
|
指出是否校验。
|
下表展示经常在命令过程中更改的进程特征。表中也给出保存这些特征的词法函数和恢复其原始设置的 DCL 命令。
特征 |
操作 |
命令或词法函数 |
控制字符
|
保存
|
F$ENVIRONMENT("CONTROL")
|
|
恢复
|
SET CONTROL
|
|
|
|
DCL 提示
|
保存
|
F$ENVIRONMENT("PROMPT")
|
|
恢复
|
SET PROMPT
|
|
|
|
默认保护
|
保存
|
F$ENVIRONMENT("PROTECTION")
|
|
恢复
|
SET PROTECTION/DEFAULT
|
|
|
|
键状态
|
保存
|
F$ENVIRONMENT("KEY_STATE")
|
|
恢复
|
SET KEY
|
|
|
|
消息格式
|
保存
|
F$ENVIRONMENT("MESSAGE")
|
|
恢复
|
SET MESSAGE
|
|
|
|
特权
|
保存
|
F$PRIVILEGE 或 F$SETPRV
|
|
恢复
|
F$SETPRV 或 SET PROCESS/PRIVILEGES
|
|
|
|
校验
|
保存
|
F$VERIFY 或 F$ENVIRONMENT
|
|
恢复
|
F$VERIFY 或 SET VERIFY
|
如果要保存进程特征,必须确保一个出错或
Ctrl/Y 中断不会引起过程在恢复其原始特征之前退出。(有关出错处理和 Ctrl/Y 中断的详情,请参阅第 13 章。)
15.2.1 更改校验设置
您可以使用 F$VERIFY 词法函数撤消在命令过程期间的校验。这阻止用户在执行过程期间显示过程的内容。
有两类校验:
- 过程校验
执行时显示每个命令行 - 映象校验
处理时显示每个数据行
按照默认,SET [NO]VERIFY 命令和 F$VERIFY 函数启用或停掉这个两类校验。一般而言,在过程中过程和映象校验设置是一样的 (两个都启用,或两个都停掉)。然而,如果决定更改这个设置,那么分别保存每个校验设置。
在以下例子中,符号 TEMP 用于允许和撤消校验:
$ ! Enable verification
$ !
$ TEMP = F$VERIFY(1)
$ LOOP:
$ INQUIRE FILE "File name"
$ IF FILE .EQS."" THEN EXIT
$ PRINT 'FILE'
$ GOTO LOOP
$ ! Disable verification
$ !
$ TEMP = F$VERIFY(0)
$ EXIT
|
在以下例子中,保存校验设置:
$ ! Save each verification state
$ ! Turn both states off
$ SAVE_VERIFY_IMAGE = F$ENVIRONMENT("VERIFY_IMAGE")
$ SAVE_VERIFY_PROCEDURE = F$VERIFY(0)
.
.
.
$ ! Restore original verification states
$ SAVE_VERIFY_IMAGE = F$VERIFY(SAVE_VERIFY_PROCEDURE,-
SAVE_VERIFY_IMAGE)
|
F$ENVIRONMENT
函数返回当前映象校验设置,并把这个值赋予符号 SAVE_VERIFY_IMAGE。然后,F$VERIFY
函数返回当前过程校验设置,并把这个值赋予符号 SAVE_VERIFY_PROCEDURE。F$VERIFY 函数撤消这两个映象和过程校验。在用 F$VERIFY 撤消校验之前,可以使用 F$ENVIRONMENT 函数获得过程校验设置。然而,在一个命令行中使用 F$VERIFY
完成这两个任务的代码较短,如上一个例子所示。
在这个过程的末端,F$VERIFY 函数恢复其原始设置 (由符号 SAVE_VERIFY_PROCEDURE 和
SAVE_VERIFY_IMAGE 指定。)
注意
如果使用时间戳,要记住只当允许校验时才应用它。有关时间戳和 SET PREFIX 命令的详情,请参阅 OpenVMS DCL Dictionary 或 DCL 求助。 |
|