Operating System - OpenVMS
cancel
Showing results for 
Search instead for 
Did you mean: 

Execute commands in variables

 
SOLVED
Go to solution
Fredrik.eriksson
Valued Contributor

Execute commands in variables

Hi,

I have a question regarding DCL scripting. My background is from Unix/Linux and now I need to write some stuff in DCL.

What I want to know (seems to be difficult to get a decent answer from google) is if it's possible to execute a command and get the resulting output string as a variable?

In bash/sh it would look something like this:
#!/bin/bash
myresult=`date`
echo $myresult

This would return what was printed to stdout (equivalent to sys$output in VMS) into the variable $myresult.

Is this possible in DCL scripting? or is there another way that is prefered in DCL scripting?

Best regards
Fredrik Eriksson
9 REPLIES 9
Joseph Huber_1
Honored Contributor

Re: Execute commands in variables


You can have bash with the GNV freeware.

DCL doesn't offer this feature directly, one has to pipe the command into a READ statement reading the output into a DCL symbol, then defining a /JOB logical from the symbol, passing the output backup to the calling process.

A simple procedure to do it looks like this:

$ if f$trnlnm("SYS$PIPE").eqs."" then EXIT
$ read/error=done/end=done sys$pipe line
$ if f$edit(line,"TRIM,COLLAPSE").nes."" then -
$ define/job 'p1' &line
$done:
$ EXIT

If the above is in DCL$PATH:LOGICAL_FROM_PIPE.COM, then use it like this:

PIPE date | @dcl$path:logical_from_pipe MYDATE
mydate = f$trnlnm("MYDATE")

Then DCL symbol mydate contains the output of the date command.

One could write that as a one line command,
PIPE date | (READ sys$pipe line ; define/job mydate &line) ,
but then error handling for the DEFINE/JOB command can make it ugly.


There is somewhere (dcl.openvms.org ?) a more general procedure logicals_from_pipe from Rob.Boyd, which can store multi-line outputs of commands/programs into an array of logicals.
http://www.mpp.mpg.de/~huber
Bojan Nemec
Honored Contributor
Solution

Re: Execute commands in variables

Fredrik,

This is no so easy in VMS. In past this problem was most times resolved by writing the output in a file and then read the file.
You can use a pipe and logical names to get the output string in a variable:

$ PIPE SHOW TIME | (READ SYS$PIPE TIM && DEFINE/JOB/NOLOG TIM &TIM)
$ !Now you have the time in the logical name tim
$ !To get it in a symbol:
$ TIM=F$TRNLNM("TIM","LNM$JOB")
$ !And a cleanup
$ DEASIGN/JOB TIM

You must use the job logical table (or any other which is visible to all subprocesses).

Bojan
Bojan
Highlighted
Jan van den Ende
Honored Contributor

Re: Execute commands in variables

Fredrik,

Welcome to VMS!

Your question is pretty generic, and therefore it has various answers.

1. MANY VMS functions are available is lexical functions F$whatever, see HELP lexical)

Just assign it to your variable (VMS terminology: SYMBOL):

myresult = F$whatever
or if you only want the display:
write sys$output F$whatever

If the result is NOT vailable as a lexical, then you can assign SYS$OUTPUT to a file; run your command; and READ that file into a symbol one record per READ; (do not forget to DELETE the file afterwards)
Instead of that, in more recent (well, less than 10 year old) versions of VMS you can construct PIPE sequences. (google SITE=ITRC & OPENVMS & PIPE for a couple of examples_

hth

If you need more, please be more specific in your question.

Proost.

Have one on me.

jpe


Don't rust yours pelled jacker to fine doll missed aches.
Fredrik.eriksson
Valued Contributor

Re: Execute commands in variables

Thank you guys for the quick responses :)

I did solve it with pipe and read as suggested above :)

Best regards
Fredrik Eriksson
Hoff
Honored Contributor

Re: Execute commands in variables

OpenVMS doesn't typically capture and process command output; Unix and Linux build pipes and process command data in this fashion, but OpenVMS does not. It's a force-fit.

OpenVMS DCL programmers tend to use I/O redirection and PIPEs as a comparative last resort, and PIPEs are a fairly recent (and bizarrely-implemented, as compared with bash) feature of OpenVMS. Lexical functions and (where available) command-generated symbols are typically used in preference to these mechanisms.

I'd suggest learning more about the implementation of DCL symbols and about logical names (neither of which really directly maps onto shell variables and file linkages), and (for most cases) forgetting about I/O redirection into symbols; into what DCL calls a shell variable. There are salient (and sometimes frustrating) differences from what you're used to with bash.

HP hasn't traditionally supported processing the output displays of commands; the structures and formats of the output of various commands has changed from release to release. It's intended to be human-readable, and most lack any concept of the machine-readable output that's suitable for shell scripts.

Or load and use bash shell, as was suggested earlier.

Fredrik.eriksson
Valued Contributor

Re: Execute commands in variables

I do agree with you, it seems rather clumsy to use the pipe-read commands to do all this.

Luckily it's just a small thing that won't need any change unless we change our SAN solution, which would make the DCL obsolete anyway.

Quite proud of myself getting it working anyway. Script attached :)
If there are things that could be improved I'm up for the discussion. There is probably alot of things that can be done easier, but since I'm somewhat new to vms I don't really know the commands :P

Best regards
Fredrik Eriksson
Jan van den Ende
Honored Contributor

Re: Execute commands in variables

Fredrik,

firstly, congrats at getting to a working solution that quick.

Now let me introduce you to some real streghts of lexicals.

>>>
$ time = f$time()
.
.
.
$ !
$ day = f$extract(8, 2, f$cvtime(time))
$ month = f$extract(5, 2, f$cvtime(time))
$ year = f$extract(0, 4, f$cvtime(time))
<<<
Can be replaced by
$ now = f$cvtime{"","comparison","date") ! get this time's date in descending format

>>>
$ !
$ if year .GES. year_exp
$ then
$ if month .GES. month_exp
$ then
$ if day .GES. day_exp
$ then
$ goto false
$ else
$ goto true
$ endif
$ else
$ goto true
$ endif
$ else
$ goto true
$ endif

$ !
$ ! If the current date is _after_ the expiration date, run this then exit
$ !
$ false:
$ pipe sense watchdog del message "''message'" /transport=tcpip 2&1> nla0:
$ sense watchdog add message "''message' ''year_exp'-''month_exp'-''day_exp'" /transport=tcpip
$ goto exit

$ !
$ ! If the current date is _before_ the expiration date, run this then exit
$ !
$ true:
$ pipe sense watchdog del message "''message'" /transport=tcpip 2&1> nla0:
$ goto exit
<<<

forget about splitting 'date', just use it
(if the interpunction is different, use
$ now = now - "-" - "-" ; can also be done if one go on f$cvtime; and remove the interpunction from 'date' analogously)
$ if now .ges. date
$ then
$ !process 'true'
$ else
$ ! process false
$ endif


Furthermore, I would move the re-submit to the beginning of the procedure. If in any way the process fails, then at least it will be waiting to run again tomorrow

Deassigning JOB (and PROCESS} logicals at the end of a batch job is superfluous: the entire table in which those are defined is deleted upon process termination.

But,
many ways lead to Rome (and have always done)

hth

Proost.

Have one on me.

jpe
Don't rust yours pelled jacker to fine doll missed aches.
Fredrik.eriksson
Valued Contributor

Re: Execute commands in variables

Thanks, I've written alot of bash scripts in my days so the basic if-then-else's wasn't really the problem :)

And I googled up some example dcl's which I found f$extract from, and then the help lexicals did the rest :)

Your solution looks alot more nifty and easier to maintain, I'll look into changing it :)

Best regards
Fredrik Eriksson
Fredrik.eriksson
Valued Contributor

Re: Execute commands in variables

This is my updated version of the script. Is this something like you were thinking Jan?

Best regards
Fredrik Eriksson