- Community Home
- >
- Servers and Operating Systems
- >
- Operating Systems
- >
- Operating System - OpenVMS
- >
- VMS Script - Search for String on a Line
Categories
Company
Local Language
Forums
Discussions
Forums
- Data Protection and Retention
- Entry Storage Systems
- Legacy
- Midrange and Enterprise Storage
- Storage Networking
- HPE Nimble Storage
Discussions
Discussions
Discussions
Forums
Discussions
Discussion Boards
Discussion Boards
Discussion Boards
Discussion Boards
- BladeSystem Infrastructure and Application Solutions
- Appliance Servers
- Alpha Servers
- BackOffice Products
- Internet Products
- HPE 9000 and HPE e3000 Servers
- Networking
- Netservers
- Secure OS Software for Linux
- Server Management (Insight Manager 7)
- Windows Server 2003
- Operating System - Tru64 Unix
- ProLiant Deployment and Provisioning
- Linux-Based Community / Regional
- Microsoft System Center Integration
Discussion Boards
Discussion Boards
Discussion Boards
Discussion Boards
Discussion Boards
Discussion Boards
Discussion Boards
Discussion Boards
Discussion Boards
Discussion Boards
Discussion Boards
Discussion Boards
Discussion Boards
Discussion Boards
Discussion Boards
Discussion Boards
Discussion Boards
Discussion Boards
Discussion Boards
Community
Resources
Forums
Blogs
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
07-05-2011 07:30 AM
07-05-2011 07:30 AM
VMS Script - Search for String on a Line
Hi,
I am working on a VMS script that was written by a former employee. The script works like I need it to besides with the addition of one If/Then statement. I am trying to get the statement to search for a particular string on a line that could have up to 5 or so other strings on the same line. However, I just need it to locate the one certain string.
An example of what the line could look like is below but it can vary and I am just needing to figure out how to have the script search this line, find the DisUser flag and if present move onto the next record.
Flags: DisCtlY Restricted DisUser DisNewMail DisReport Captive
Below is a piece of the script that I am working with as well. As you can see in the middle there is a statement that is trying to search for the DisUser string. However, instead of skipping the records with this string it still includes them in the file it writes.
$ GETREC: $ read/end=quit infile rec $ if (f$locate("Username:",rec) .eq. 0) .and. (f$locate(":",rec) .ne. 0) $ then usr = f$extract(10,9,rec) $ endif $ if (f$locate("Flags",rec) .eqs. "DisUser") $ then goto getrec $ endif $ if (f$locate("Last Login:",rec) .eq. 0) .and. (f$locate(":",rec) .ne. 0) $ then date1 = f$extract(12,11,rec) $ date2 = f$extract(45,11,rec) $ else goto getrec $ endif
Thank you in advance for any help or assistance.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
07-05-2011 07:54 AM
07-05-2011 07:54 AM
Re: VMS Script - Search for String on a Line
Here's the basic logic to check for the existence of a substring within the specified string:
$ if f$locate("DisUser",rec) .ne. f$length(rec) then write sys$output "Found DisUser"
I'd probably change that to the following to force the search string to single-spaced and trimmed uppercase text, and tweak the search as follows:
$ rec = f$edit(rec,"UPCASE,COMPRESS,TRIM") ! or analogous
$ if f$locate("DISUSER",rec) .ne. f$length(rec) then write sys$output "Found DisUser"
And FWIW, parsing the output of commands and utilities is generally considered unsupported and fragile. What you have probably adapts, but changes to the command or utility output can cause weird run-time errors.
As for alternatives, there is the GETUAI tool. This uses documented interfaces to access SYSUAF.
I'd also suggest reading the OpenVMS User's Manual in the OpenVMS documentation shelf, if you're unfamiliar with DCL programming and DCL command procedures.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
07-05-2011 08:03 AM
07-05-2011 08:03 AM
Re: VMS Script - Search for String on a Line
The author of the script is confused on the use of f$Locate. The return value is an integer, either a byte offset beginning with zero if the substring is found, or the length of the string being searched if the substring is not found. See $ HELP LEXICAL F$LOCATE.
That said, the first IF statement's second clause is superfluous since if "Username:" is found at byte offset zero then there cannot also be a ":" at byte offset zero.
The IF statement for the "DisUser" is completely wrong.
I would suggest something like
$ IF f$Locate("Flags:", rec) .ne. f$Length(rec) ! This is the Flags line
$ Then
$ IF f$Locate("DisUser") .ne. f$Length(rec) Then GoTo getrec
$ EndIf
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
07-05-2011 08:42 AM
07-05-2011 08:42 AM
Re: VMS Script - Search for String on a Line
>> ind the DisUser flag and if present move onto the next record.
I don't think that is really what you want, unless you mean 'next sysuaf record' versus next record in listing.
I strongly suspect that the script should not just skip that line, but skip everything else for that username.
For that the script needs to maintain a flag to remember the event.
Personally I often prefer to use a multi-purpose 'skip' flag versus a specific 'disuser_seen' flag.
The code might then ROUGHLY look like:
$ close/nolog infile $ open /read infile sysuaf.lis $ $ skip = 0 $ GETREC: $ read/end=quit infile rec $ len = f$length(rec) $ if f$extract (0,9,rec) .EQS. "Username:" $ then $ skip = 0 $ usr = f$extract(10,9,rec) $ endif $ IF (f$extract (0,6,rec).EQS."Flags:") .AND. (len .NE. f$locate("DisUser",rec)) THEN skip = 1 $ IF skip THEN GOTO getrec $ if (f$locate("Last Login:",rec) .eq. 0) .and. (f$locate(":",rec) .ne. 0) $ then $ date1 = f$extract(12,11,rec) $ date2 = f$extract(45,11,rec) $ WRITE SYS$OUTPUT usr, " ", date1, " ", date2 $ skip = 1 ! All done untill next "Username:" $ endif $ goto getrec $quit: $ CLOSE infile
Hein.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
07-05-2011 09:15 AM
07-05-2011 09:15 AM
Re: VMS Script - Search for String on a Line
Thanks for the quick replies.
Yes, I do mean the next sysauf record. What the script is doing is writing users to a file but I am needing to omit the users who have this DisUser flag from the file.
Thanks,
Mike
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
07-05-2011 10:06 AM
07-05-2011 10:06 AM
Re: VMS Script - Search for String on a Line
If all you are trying to do is separate "DisUser'd" accounts from the rest, you might want to consider using the "/Brief" output from the SYSUAF. This way you get 1 line per account, and the the DISUSER flag will be the last item on the line, (if the account is disusered)
$ mc authorize show /brief smithd
Owner Username UIC Account Privs Pri Directory
David Smith SMITHD [120,4127] 912 All 4 Disuser
The obvious advantage is that there is less garbage to churn through.
Having said that, you should look in to using GETUAI utility, as suggested by Hoff.
Dave.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
07-05-2011 10:47 AM
07-05-2011 10:47 AM
Re: VMS Script - Search for String on a Line
The problem with the GETUAI utility that a couple of people have suggested is that it doesn't really fit the problem being presented, which appears to be to query for all the usernames that have not been disusered. As far as I can tell, with GETUAI you have to already know the username you are interested in. You'd still have loop over a listing or SYSUAF.DAT itself to find out what all the usernames are and then test each one for whether it's been disusered.
Joe Meadows' UAF utility, on the other hand, makes querying easy. Just do:
$ uaf/select=flags=nodisuser/display=username
It's available from:
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
07-05-2011 10:50 AM
07-05-2011 10:50 AM
Re: VMS Script - Search for String on a Line
You may want to use search to reduce and select the wanted information. Something like
$ pipe define/user sysuaf sys$system:sysuaf ; mc authorize show * |search sys$input Username:,Flags: |search sys$input DisUser/match=nand/out=x.lis
$ pipe search x.lis Flags:/wind=(1,0) |search sys$input Username:
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
07-05-2011 10:57 AM
07-05-2011 10:57 AM
Re: VMS Script - Search for String on a Line
So are you all set now with the various suggestions?
btw 1... careful with the hardcoded 9 character username.
OpenVMS itself supports 12.
Btw 2... I 'happened' to have a bit of DCL which possibly does pretty much what you want.
It can go straight for SYSUAF (local copy in example below).
And yeah, it could flip the disuser bit and update as well, but I prefer to go through a file.
$! $! uaf_lastlogin.com Hein van den Heuvel,August 2007. $ $! List records from SYSUAF for which the Last Interactive Login is more $! than 'p1' days ago (default 90). $ $IF p1.eqs."" THEN p1 = "90" $cutoff_date = f$cvtime("TODAY -''p1'-") $!libr/extr=$uafdef/out=uafdef.tmp sys$library:lib.mlb $!sea uafdef.tmp flag... $!EQU UAF$Q_LASTLOGIN_I 396 $!EQU UAF$L_FLAGS 468 $!EQU UAF$V_DISACNT 4 $ $define sysuaf sys$disk:[]sysuaf.dat ! Local copy for testting $sysuaf = f$parse("SYSUAF","SYS$SYSTEM:.DAT",,,"SYNTAX_ONLY") $open /read/share=write uaf 'sysuaf' $loop: $ read/end=done uaf rec $ lastlogin_bin = F$EXTR(396,8,rec) $ lastlogin_asc = F$FAO("!%D",f$cvui(32,32,f$fao("!AD",8,lastlogin_bin))) $ IF f$cvtime(lastlogin_asc) .GTS. cutoff_date THEN GOTO loop $ IF f$cvsi(468*8+4,1,rec) THEN GOTO loop ! disuser already? $ username = F$EXTRACT(4,12,rec) $ WRITE SYS$OUTPUT "MODIFY ''username' /FLAG=DISUSEER ! Last Login: ", lastlogin_asc $ GOTO loop $done: $close uaf
Also, a similar script using perl....
while (<>) { if (/^Username:(.{9})/) { $skip = 0; $user = $1; } next if $skip; $skip = 1 if /^Flags.*DisUser/; if (/^Last Login:.(.{11}).{22}(.{11})/) { print qq($user $1 $2\n); $skip = 1; } }
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
07-05-2011 12:19 PM
07-05-2011 12:19 PM
Re: VMS Script - Search for String on a Line
Yeah, the suggestions help give a bit of a clearer picture as to how some of this works. It is always difficult to work with a new language plus try to figure out what the previous person was doing.
The way this was setup was to compare dates to see who has not logged on in 90 days, the user does not have a DisUser flag already and then write the Username plus dates to a .dat file. Then, you run another script that actually goes through the .dat file created and DisUser's all the usernames. I believe we write to the file with one script do allow us to proof the usernames before going ahead and setting the DisUser flag.
Just so you guys can see here is the entire script that searches through the sysuaf.lis file for the users.
$ ! $ set noverify $ set noon $ ! $ compdt = "28-FEB-2008" $ defdt = "01-JUL-2008" $ ! $ if p1 .nes. "" $ then compdt = p1 $ write sys$output "Compare date is " + compdt $ else $ write sys$output "No comparison date included." $ goto quit $ endif $ ! $ set def sys$system $ uaf := "$authorize" $ uaf list * /full $ set def mvx $ open/read infile sys$system:sysuaf.lis $ open/write outfile uaf_old_accts.dat $ GETREC: $ read/end=quit infile rec $ if (f$locate("Username:",rec) .eq. 0) .and. (f$locate(":",rec) .ne. 0) $ then usr = f$extract(10,9,rec) $ endif $ if (f$locate("Last Login:",rec) .eq. 0) .and. (f$locate(":",rec) .ne. 0) $ then date1 = f$extract(12,11,rec) $ date2 = f$extract(45,11,rec) $ else goto getrec $ endif $ if date1 .eqs. " " then date1 = defdt $ if date2 .eqs. " " then date2 = defdt $ if (f$cvtime(date1,,) .lts. f$cvtime(compdt,,)) .and. - (f$cvtime(date2,,) .lts. f$cvtime(compdt,,)) then goto writerec $ goto getrec $ WRITEREC: $ wrtrec = usr+" "+date1+" - "+date2 $ write outfile wrtrec $ goto getrec $ QUIT: $ close infile $ close outfile $ exit [End of file]
Thanks!