Date: Tue, 20 Jan 87 11:50:04 est From: David Krowitz Subject: New version of BATCH program Status: RO I just found out that I left out one of the files in my previous distribution of the BATCH program. Here is a corrected version of the distribution. Run it through /bin/sh to unpack it. -- David Krowitz ----------------------------------------------------------------- #! /bin/sh # This is a shell archive, meaning: # 1. Remove everything above the #! /bin/sh line. # 2. Save the resulting text in a file. # 3. Execute the file with /bin/sh (not csh) to create the files: # batch.dir # This archive created: Tue Jan 20 11:47:51 1987 export PATH; PATH=/bin:$PATH if test ! -d 'batch.dir' then mkdir 'batch.dir' fi cd 'batch.dir' if test -f 'batch' then echo shar: will not over-write existing file "'batch'" else cat << \SHAR_EOF > 'batch' /users/userlib/com/parse_batch ^1 ^2 ^3 ^4 ^5 ^6 ^7 ^8 ^9 ^10 ^11 ^12 ^13 ^14 ^15 | /com/sh SHAR_EOF chmod +x 'batch' fi # end of overwriting check if test -f 'parse_batch.pas' then echo shar: will not over-write existing file "'parse_batch.pas'" else cat << \SHAR_EOF > 'parse_batch.pas' program parse_batch(input, output); { This program parses batch input and outputs a command to be passed to the command interpreter. The idea is to change standard Apollo input format into the strange format required for creating remote processes. The real advantage is when names are defaulted. The following major change was introduced with version 1.0: Make batch take advantage of the sh_log program, which uses a log file to keep track of BOTH error and standard input. batch -pn name -n node_id -log logfilename shell_command shell_parameters is converted to crp '/com/sh_log -c @'shell_command shell_params@' -l logfilename' -on node_id -n name -cps -me with appropriate defaults IMPLEMENTATION NOTES: This program depends on there being a "sh_log" program available. Currently this needs to be in /com/sh_log. This can be changed by changing the line in the start_output procedure which refers to /com/sh_log to be anywhere the user desires. NOTES, PROBLEMS, RESTRICTIONS, ETC: See the output_help procedure for these. Algorithm summary: This is mostly a bookkeeping problem. The arguments to batch are parsed off and written in the other syntax for input to sh_log. Note that any parameter to batch which is NOT a switch is assumed to be the shell command (or script) to execute, along with any of its parameters. The command itself (shell_command above) is parsed to obtain the leaf name; this leaf name is used to derive the default logfile and process names. } const max_arguments = 30; {maximum # of arguments on command line} program_version = 1.35; {update history: version 1.1 10/14/85 slp change sh_log to `node_data/sh_log version 1.2 10/29/85 slp for SR9 -- use CRP -ME to transfer SID version 1.3 2/12/86 slp change help file to reflect version 1.2 change; also allow /dev/null for logfile version 1.35 3/21/86 slp for ADUS -- use /com/sh_log instead of `node_data/com/sh_log} %include '/sys/ins/base.ins.pas'; %include '/sys/ins/name.ins.pas'; %include '/sys/ins/pgm.ins.pas'; %include '/sys/ins/pm.ins.pas'; %include '/sys/ins/streams.ins.pas'; %include '/sys/ins/vfmt.ins.pas'; type pathtype = record name: name_$pname_t; length: integer end; var process_name, logfile_name, full_log, command, full_command, username, wd, node_id: pathtype; name_specified, node_specified, logfile_specified, command_specified, silent_specified: boolean; misc_status: status_$t; i: integer; devnull: array[1..*] of char := '/dev/null'; {special name for logfile directed to the null device} devnull_size: integer := sizeof(devnull); procedure init_globals; begin {init_globals} node_id.length := 1; node_id.name[1] := '/'; name_specified := false; logfile_specified := false; command_specified := false; node_specified := false; silent_specified := false; end; {init_globals} function exists(var f: pathtype): boolean; {This function returns true if the specified file exists} var file_attributes: stream_$ir_rec_t; stream_mask: stream_$inquire_mask_t; {which attributes to get} stream_inq_type: stream_$ir_opt; {how to access file (by name)} stream_error_mask: stream_$inquire_mask_t; {status returned} i: integer; begin {exists} stream_mask:= []; {Don't really need any information} stream_inq_type := stream_$name_unconditional; for i := 1 to f.length do begin file_attributes.obj_name[i] := f.name[i]; end; file_attributes.obj_namlen := f.length; file_attributes.pre_exist := false; stream_$inquire( stream_mask, stream_inq_type, file_attributes, stream_error_mask, misc_status); exists := (misc_status.code <> stream_$name_not_found); end; {exists} function is_null(var f: pathtype): boolean; {This function returns true if the specified file is /dev/null} var i: integer; null: boolean; {local variable for value holder} begin {is_null} if f.length <> devnull_size then is_null := false else begin null := true; i := 1; repeat if f.name[i] <> devnull[i] then null := false; i := i + 1; until (not null) or (i > devnull_size); is_null := null; end; end; {is_null} procedure start_output; begin write('crp ''/com/sh_log -v -c @''wd '); {Note: this can be customized to include a startup script} for i := 1 to wd.length do write(wd.name[i]); write(';'); end; procedure output_help; begin {output_help} vfmt_$ws2(stream_$errout,'batch revision %4.2F, 85/5/xx by SLP at Mentor APD%.',program_version,0); vfmt_$ws2(stream_$errout,'BATCH -- submit a command as a background (CPS) process%.',i,i); vfmt_$ws2(stream_$errout,'usage: BATCH pathname [-N nodeid] [-PN process_name]%.',i,i); vfmt_$ws2(stream_$errout,' [-L logfile] [-Silent]%.',i,i); vfmt_$ws2(stream_$errout,'%.',i,i); vfmt_$ws2(stream_$errout,'%.',i,i); vfmt_$ws2(stream_$errout,'%.',i,i); vfmt_$ws2(stream_$errout,'FORMAT%.',i,i); vfmt_$ws2(stream_$errout,'%.',i,i); vfmt_$ws2(stream_$errout,' BATCH pathname %.',i,i); vfmt_$ws2(stream_$errout,'%.',i,i); vfmt_$ws2(stream_$errout,'%.',i,i); vfmt_$ws2(stream_$errout,' BATCH creates a background process on the given node and has the%.',i,i); vfmt_$ws2(stream_$errout,' process execute the given command. The process executes with the same%.',i,i); vfmt_$ws2(stream_$errout,' id as the calling process, in the same working directory as the process.%.',i,i); vfmt_$ws2(stream_$errout,'%.',i,i); vfmt_$ws2(stream_$errout,'%.',i,i); vfmt_$ws2(stream_$errout,'ARGUMENTS%.',i,i); vfmt_$ws2(stream_$errout,'%.',i,i); vfmt_$ws2(stream_$errout,' pathname The shell command to be executed. This may be any%.',i,i); vfmt_$ws2(stream_$errout,' command recognized by the command interpreter; thus%.',i,i); vfmt_$ws2(stream_$errout,' it may be a shell script or an object file.%.',i,i); vfmt_$ws2(stream_$errout,' If the command has arguments, enclose the command%.',i,i); vfmt_$ws2(stream_$errout,' AND any arguments in quotes. For example:%.',i,i); vfmt_$ws2(stream_$errout,' BATCH "netstat -a"%.',i,i); vfmt_$ws2(stream_$errout,'%.',i,i); vfmt_$ws2(stream_$errout,'%.',i,i); vfmt_$ws2(stream_$errout,'OPTIONS%.',i,i); vfmt_$ws2(stream_$errout,'%.',i,i); vfmt_$ws2(stream_$errout,' -N nodeid Execute the process on the given node.%.',i,i); vfmt_$ws2(stream_$errout,'%.',i,i); vfmt_$ws2(stream_$errout,' Default if omitted: Execute on current node%.',i,i); vfmt_$ws2(stream_$errout,'%.',i,i); vfmt_$ws2(stream_$errout,' -PN name Use given name as process name.%.',i,i); vfmt_$ws2(stream_$errout,'%.',i,i); vfmt_$ws2(stream_$errout,' Default if omitted: Use BATCH.username.commandname%.',i,i); vfmt_$ws2(stream_$errout,'%.',i,i); vfmt_$ws2(stream_$errout,' -L logfile Direct output to given file. Note that if no output%.',i,i); vfmt_$ws2(stream_$errout,' is desired, logfile may be specified as /dev/null.%.',i,i); vfmt_$ws2(stream_$errout,' Please note also that with version 1.0 of BATCH, both standard%.',i,i); vfmt_$ws2(stream_$errout,' and error output are written to the same log file, and that%.',i,i); vfmt_$ws2(stream_$errout,' this log file also includes the commands executed.%.',i,i); vfmt_$ws2(stream_$errout,'%.',i,i); vfmt_$ws2(stream_$errout,' Default if omitted: Use commandname.log in current%.',i,i); vfmt_$ws2(stream_$errout,' working directory.%.',i,i); vfmt_$ws2(stream_$errout,'%.',i,i); vfmt_$ws2(stream_$errout,' -Silent Don''t tell me about the process to be created%.',i,i); vfmt_$ws2(stream_$errout,'%.',i,i); vfmt_$ws2(stream_$errout,'%.',i,i); vfmt_$ws2(stream_$errout,'PROBLEMS, RESTRICTIONS%.',i,i); vfmt_$ws2(stream_$errout,'%.',i,i); vfmt_$ws2(stream_$errout,' 1. Error reporting is minimal. The following errors are not%.',i,i); vfmt_$ws2(stream_$errout,' reported;%.',i,i); vfmt_$ws2(stream_$errout,' a. pname same as another process%.',i,i); vfmt_$ws2(stream_$errout,' b. log file same as that of another process%.',i,i); vfmt_$ws2(stream_$errout,' c. command doesn''t exist%.',i,i); vfmt_$ws2(stream_$errout,' d. logfile or process name invalid%.',i,i); vfmt_$ws2(stream_$errout,' e. remote node not set up for remote server processes%.',i,i); vfmt_$ws2(stream_$errout,'%.',i,i); vfmt_$ws2(stream_$errout,' 2. Ideally we''d like to transfer across csr to background%.',i,i); vfmt_$ws2(stream_$errout,' process. Currently only wd is transferred across directly. The%.',i,i); vfmt_$ws2(stream_$errout,' user could customize by adding a startup script. The aim here%.',i,i); vfmt_$ws2(stream_$errout,' would be: If we can type a command at the shell level, we can%.',i,i); vfmt_$ws2(stream_$errout,' precede the command by "batch" and achieve the same results.%.',i,i); vfmt_$ws2(stream_$errout,'%.',i,i); vfmt_$ws2(stream_$errout,'EXAMPLES%.',i,i); vfmt_$ws2(stream_$errout,'%.',i,i); vfmt_$ws2(stream_$errout,' 1. $ BATCH pas myfile%.',i,i); vfmt_$ws2(stream_$errout,'%.',i,i); vfmt_$ws2(stream_$errout,' This creates a process to compile the file myfile.pas%.',i,i); vfmt_$ws2(stream_$errout,' in the current directory. The process name will be%.',i,i); vfmt_$ws2(stream_$errout,' batch.slp.pas, and the log file will be pas.log%.',i,i); vfmt_$ws2(stream_$errout,' in the current working directory.%.',i,i); vfmt_$ws2(stream_$errout,'%.',i,i); vfmt_$ws2(stream_$errout,' 2. $ BATCH my_shell_script -n 2846%.',i,i); vfmt_$ws2(stream_$errout,'%.',i,i); vfmt_$ws2(stream_$errout,' This process is created on another node.%.',i,i); end; {output_help} procedure get_arguments; var arg_no: integer; arg: pathtype; misc_status: status_$t; i,j: integer; {loop counters} procedure get_switch; begin {get_switch} for i := 1 to arg.length do {Convert to lower case} if (arg.name[i] >= 'A') and (arg.name[i] <= 'Z') then arg.name[i] := chr (ord (arg.name[i]) + 32); if (arg.name[2] = 'h') then begin output_help; pgm_$exit; end else if (arg.name[2] = 'p') then begin arg_no := arg_no + 1; process_name.length := pgm_$get_arg( arg_no, process_name.name, misc_status, name_$pnamlen_max); name_specified := true; end else if ((arg.name[2] = 'o') or (arg.name[2] = 'n')) then begin arg_no := arg_no + 1; node_id.length := pgm_$get_arg( arg_no, node_id.name, misc_status, name_$pnamlen_max); node_specified := true; end else if (arg.name[2] = 'l') then begin arg_no := arg_no + 1; logfile_name.length := pgm_$get_arg( arg_no, logfile_name.name, misc_status, name_$pnamlen_max); logfile_specified := true; end else if (arg.name[2] = 's') then begin silent_specified := true; end else begin vfmt_$ws2(stream_$errout,'?Unrecognized switch %A%.',arg.name, arg.length); pgm_$exit; end; {case if on switch type} end; {get_switch} begin {get_arguments} for arg_no := 1 to max_arguments do begin arg.length := pgm_$get_arg( arg_no, arg.name, misc_status, name_$pnamlen_max); if (arg.length > 0) then begin if (arg.name[1] = '-') then {if it's a switch} get_switch else begin {if not a switch, assume must be written to command} for i := 1 to arg.length do begin write(arg.name[i]); end; write(' '); if not command_specified then begin {if first non-switch, parse off leaf as command} j := 0; i := 0; while (i '.')) do begin i := i + 1; end; username.length := i - 1; name_$get_wdir(wd.name,wd.length,misc_status); for i := 1 to wd.length do begin if (wd.name[i] >= 'A') and (wd.name[i] <= 'Z') then wd.name[i] := chr (ord (wd.name[i]) + 32); end; end; {get_procinfo} procedure do_logfile; var i_full: integer; {location in full_log name} begin if (not silent_specified) then begin vfmt_$ws2(stream_$errout,'Working directory of created process will be %A%.',wd.name,wd.length); end; if logfile_specified then begin if logfile_name.name[1] = '/' then begin if ((logfile_name.name[2] <> '/') and node_specified) then begin vfmt_$ws2(stream_$errout,'?Warning: logfile specification begins with ''/''%.', i,i); end; for i_full := 1 to logfile_name.length do begin full_log.name[i_full] := logfile_name.name[i_full]; end; full_log.length := logfile_name.length; end else begin for i_full := 1 to wd.length do begin full_log.name[i_full] := wd.name[i_full]; end; full_log.name[wd.length+1] := '/'; for i_full := wd.length+2 to (wd.length + logfile_name.length+1) do begin full_log.name[i_full] := logfile_name.name[i_full-wd.length-1]; end; full_log.length := wd.length + logfile_name.length + 1; end; end else begin for i_full := 1 to wd.length do begin full_log.name[i_full] := wd.name[i_full]; end; full_log.name[wd.length+1] := '/'; for i_full := wd.length+2 to (wd.length + command.length + 1) do begin full_log.name[i_full] := command.name[i_full - wd.length-1]; end; i_full := wd.length + command.length + 1; full_log.name[i_full+1] := '.'; full_log.name[i_full+2] := 'l'; full_log.name[i_full+3] := 'o'; full_log.name[i_full+4] := 'g'; full_log.length := wd.length + command.length + 5; end; {if specified else endif} if (not is_null(full_log)) then begin {If we haven't specified /dev/null as the filename} if (exists(full_log)) then begin vfmt_$ws2(stream_$errout,'?logfile %A already exists.%.',full_log.name,full_log.length); pgm_$exit; end; write('@'' -l '); for i := 1 to full_log.length do write(full_log.name[i]); write(''''); if (not silent_specified) then begin vfmt_$ws2(stream_$errout,'Logfile will be %A%.',full_log.name,full_log.length); end; end else begin {else it was /dev/null} write('@'''''); if (not silent_specified) then begin vfmt_$ws2(stream_$errout,'Logfile will not be created%.',0,0); end; end; {if not /dev/null else} end; procedure do_name; var i: integer; begin write(' -n '); if name_specified then begin for i := 1 to process_name.length do write(process_name.name[i]); if (not silent_specified) then begin vfmt_$ws2(stream_$errout,'Process name will be %A%.',process_name.name,process_name.length); end; end else begin write('batch.'); for i := 1 to username.length do write(username.name[i]); write('.'); for i := 1 to command.length do write(command.name[i]); if (not silent_specified) then begin vfmt_$ws5(stream_$errout,'Process name will be batch.%A.%A%.',username.name,username.length,command.name,command.length,0); end; end; end; procedure do_nodeid; var i: integer; begin write (' -on '); for i := 1 to node_id.length do write(node_id.name[i]); writeln(' -cps -me'); if (not silent_specified) then begin if (node_specified) then begin vfmt_$ws2(stream_$errout,'Process will be created on node %A%.',node_id.name,node_id.length); end else begin vfmt_$ws2(stream_$errout,'Process will be created on this node.%.',0,0); end; end; end; begin {parse_batch main} init_globals; get_procinfo; start_output; get_arguments; if not command_specified then begin vfmt_$ws2(stream_$errout,'?No command specified%.', i,i); pgm_$exit; end; do_logfile; do_name; do_nodeid; end. {parse_batch main} SHAR_EOF chmod +x 'parse_batch.pas' fi # end of overwriting check if test -f 'sh_log.pas' then echo shar: will not over-write existing file "'sh_log.pas'" else cat << \SHAR_EOF > 'sh_log.pas' program shell_with_log; { Author: Steven Pucci, Mentor APD Date: May 29, 1985 This program is functionally equivalent to the /com/sh program, with the exception that it directs both error and standard output to a file specified with the -l argument. It parses off the -l logname arguments from its own argument list, opens the specified file, and invokes /com/sh with the remaining arguments. It passes the stream number for the opened file to both error output and standard output for the invoked program. This program should work even if /com/sh is changed substantially, since the real /com/sh is invoked to do the real work. The only change to /com/sh which would necessitate recompiling this program would be the addition of an argument to /com/sh which starts with -l. } %include '/sys/ins/base.ins.pas'; %include '/sys/ins/error.ins.pas'; %include '/sys/ins/pgm.ins.pas'; %include '/sys/ins/streams.ins.pas'; %include '/sys/ins/vfmt.ins.pas'; const program_version = 1.1; {History: 1.1 2/12/86 slp Allowed sh_log with no -l to invoke sh transparently so the "batch -l /dev/null" command will work} type pathtype = record name: name_$pname_t; length: integer end; var status: status_$t; stream_id: stream_$id_t; {stream id of log file} ec: uid_$t; {reserved -- no documentation} stream_vector: array[1..4] of stream_$id_t; {to pass to /com/sh} wait_mode: pgm_$mode; {of invoke of /com/sh} logfile_name: pathtype; logfile_specified: boolean; argument_vector_pointer: pgm_$argv_ptr; num_args: integer; arg: pathtype; {holds arguments for comparison} procedure output_help; begin {output_help} vfmt_$write2('sh_log (shell_with_log_file) revision %3.1F, 85/3/xx%.',program_version,0); writeln('SH_LOG'); writeln(' Author: Steve Pucci at Mentor APD'); writeln; writeln('This program is functionally equivalent to the sh program, with one exception:'); writeln('there is an additional switch option to create a log file. All other options'); writeln('to sh are available; type HELP SH for details on the other options. Please note'); writeln('that this program is most useful when run as a background process.'); writeln; writeln('FORMAT:'); writeln; writeln(' sh_log [options to the sh command] -l logfilename'); writeln; writeln('OPTIONS:'); writeln; writeln(' -l logfilename The name of a file to be created which will contain'); writeln(' all standard and error output from the shell program.'); writeln(' Note that if the -v switch is also specified, the'); writeln(' commands executed by the shell program will also be'); writeln(' written to the logfile.'); writeln; writeln(' all options to sh See HELP SH for details.'); writeln; writeln; writeln('EXAMPLES:'); writeln; writeln(' 1. sh_log pas myfile -l myfilename'); writeln; writeln(' Executes the shell command "pas myfile," and directs the output to the'); writeln(' file myfilename.'); writeln; writeln(' 2. sh_log myscript -v -l myfilename'); writeln; writeln(' Executes the shell script myscript, and directs the output to the file'); writeln(' myfilename. Note that since -v is specified, the commands in myscript'); writeln(' are also written to the file.'); end; {output_help} procedure parse_arguments; { The idea is to pass everything through to /com/sh, with the exception of the -l logfile argument which we strip off, and the -h argument for help. The strange loop logic is necessary to retrieve the arguments properly. We need to get num_args arguments, but the argument pointer changes as we delete arguments from the vector. See the description of the pgm routines for details. } var i: integer; {loop counter} arg_no: integer; {argument number} begin {parse_arguments} logfile_specified := false; pgm_$get_args( num_args, argument_vector_pointer ); i := 0; {i is number of arguments retrieved so far} arg_no := 1; {arg_no is pointer to next argument -- no, I can't do this with one loop variable} while (i < num_args-1) do begin {the 0th arg is the program name} arg.length := pgm_$get_arg( arg_no, arg.name, status, name_$pnamlen_max ); if ( (arg.name[1] = '-') and ((arg.name[2] = 'l') or (arg.name[2] = 'L'))) then begin if logfile_specified then begin vfmt_$ws2(stream_$errout,'?More than one logfile specified%.',0,0); pgm_$exit; end; {if more than one logfile} pgm_$del_arg(arg_no); {remove the -l from the arg list} logfile_name.length := pgm_$get_arg(arg_no, logfile_name.name, status, name_$pnamlen_max ); if (status.all <> status_$ok) then begin vfmt_$ws2(stream_$errout,'?Trouble getting logfile argument%.',0,0); error_$print(status); end; logfile_specified := true; pgm_$del_arg(arg_no); {remove the logfile name from the arg list} i := i + 2; {we already did two more args} end else if ( (arg.name[1] = '-') and ((arg.name[2] = 'h') or (arg.name[2] = 'H'))) then begin output_help; pgm_$exit; end else begin {if not the -l or the -h argument, increment arg ptr} arg_no := arg_no + 1; i := i + 1; end; {if it was the -l argument} end; {while loop on argument number} if not logfile_specified then begin vfmt_$ws2(stream_$errout,'?No logfile specified -- use /com/sh; continuing anyway...%.',0,0); { pgm_$exit; We want it to continue anyway so that batch works properly when /dev/null is specified} end; {if no logfile specified} end; {parse_arguments} procedure open_logfile; begin {open_logfile} stream_$create(logfile_name.name, logfile_name.length, stream_$write, stream_$unregulated, stream_id, status); if status.all <> status_$ok then begin vfmt_$ws2(stream_$errout,'?Trouble creating file %A%.', logfile_name.name, logfile_name.length); error_$print(status); pgm_$exit; end; end; {open_logfile} procedure invoke_shell; begin {invoke shell} stream_vector[1] := stream_$stdin; {std input for /com/sh} stream_vector[3] := stream_$errin; {err input for /com/sh} if logfile_specified then begin stream_vector[2] := stream_id; {std output for /com/sh} stream_vector[4] := stream_id; {err output for /com/sh} num_args := num_args - 2; {leave off file specification} end else begin stream_vector[2] := stream_$stdout; {std output for /com/sh} stream_vector[4] := stream_$errout; {err output for /com/sh} end; wait_mode := [pgm_$wait]; pgm_$invoke('/com/sh', 7, num_args, argument_vector_pointer^, 4, stream_vector, wait_mode, ec, status ); if status.all <> status_$ok then begin vfmt_$ws2(stream_$errout,'?Trouble with invoke of /com/sh%.',0,0); error_$print(status); pgm_$exit; end; end; {invoke shell} begin {shell_with_log} parse_arguments; if logfile_specified then open_logfile; invoke_shell; end. {shell_with_log} SHAR_EOF chmod +x 'sh_log.pas' fi # end of overwriting check if test -f 'a.readme' then echo shar: will not over-write existing file "'a.readme'" else cat << \SHAR_EOF > 'a.readme' written by : Steve Pucci Mentor Graphics 408-436-1500 DESCRIPTION: The batch command allows you to SIMPLY create a batch process on a node, either the local one or a remote one. Simply typing BATCH shell-script-name invokes a batch job on the local node; parameters can be specified to run on another node. This command is useful primarily for 1. People who wish to run long overnight jobs without staying logged in, and 2. People who log in over SIO lines and want to run more than one process at the same time. The BATCH.HLP file is just a copy of what happens if you type BATCH -H REQUIRED FILES: The "batch" set contains the following files: 1. The batch shell script (a one-line file) 2. The parse_batch.bin file (parses the batch command) 3. The parse_batch.pas file (source for parse_batch.bin) 4. The sh_log file (runs a shell script, directing both standard and error output to the same logfile) 5. The sh_log.pas file (source for sh_log) 6. The batch.hlp file (copy of the help for BATCH). 7. The a.readme file (this file) INSTALLATION: 1. Place parse_batch.bin in an appropriate place on the network (anywhere executables are stored; can be user directory) 2. Edit batch and change the reference to parse_batch.bin to reflect the correct location of parse_batch.bin 3. Put batch somewhere in your command search rules 4. Put sh_log in /com on all nodes that will have batch jobs running on them. (If you want to put sh_log somewhere other than /com, you need to edit parse_batch.pas, and change the reference to /com/sh_log to wherever you want to put it. Then you would need to recompile parse_batch with the Pascal compiler). 5. Type batch -help for details on how to use it. SHAR_EOF chmod +x 'a.readme' fi # end of overwriting check if test -f 'batch.hlp' then echo shar: will not over-write existing file "'batch.hlp'" else cat << \SHAR_EOF > 'batch.hlp' batch revision 1.35, 85/5/xx by SLP at Mentor APD BATCH -- submit a command as a background (CPS) process usage: BATCH pathname [-N nodeid] [-PN process_name] [-L logfile] [-Silent] FORMAT BATCH pathname BATCH creates a background process on the given node and has the process execute the given command. The process executes with the same id as the calling process, in the same working directory as the process. ARGUMENTS pathname The shell command to be executed. This may be any command recognized by the command interpreter; thus it may be a shell script or an object file. If the command has arguments, enclose the command AND any arguments in quotes. For example: BATCH "netstat -a" OPTIONS -N nodeid Execute the process on the given node. Default if omitted: Execute on current node -PN name Use given name as process name. Default if omitted: Use BATCH.username.commandname -L logfile Direct output to given file. Note that if no output is desired, logfile may be specified as /dev/null. Please note also that with version 1.0 of BATCH, both standard and error output are written to the same log file, and that this log file also includes the commands executed. Default if omitted: Use commandname.log in current working directory. -Silent Don't tell me about the process to be created PROBLEMS, RESTRICTIONS 1. Error reporting is minimal. The following errors are not reported; a. pname same as another process b. log file same as that of another process c. command doesn't exist d. logfile or process name invalid e. remote node not set up for remote server processes 2. Ideally we'd like to transfer across csr to background process. Currently only wd is transferred across directly. The user could customize by adding a startup script. The aim here would be: If we can type a command at the shell level, we can precede the command by "batch" and achieve the same results. EXAMPLES 1. $ BATCH pas myfile This creates a process to compile the file myfile.pas in the current directory. The process name will be batch.slp.pas, and the log file will be pas.log in the current working directory. 2. $ BATCH my_shell_script -n 2846 This process is created on another node. SHAR_EOF chmod +x 'batch.hlp' fi # end of overwriting check if test -f 'batch.bld' then echo shar: will not over-write existing file "'batch.bld'" else cat << \SHAR_EOF > 'batch.bld' von pas parse_batch.pas bind -b parse_batch parse_batch.bin dlf parse_batch.bin pas sh_log.pas bind -b sh_log sh_log.bin dlf sh_log.bin voff SHAR_EOF chmod +x 'batch.bld' fi # end of overwriting check if test -f 'parse_batch' then echo shar: will not over-write existing file "'parse_batch'" else cat << \SHAR_EOF > 'parse_batch' J J"d$*%% B'Hm lHz& m rHzv m HzF m tHz. m DHz~ m PHzV m dHz m HzrN/HzHHzm m EXISTShe IS_NULL>x  START_OUTPUTx  ( OUTPUT_HELPF  GET_SWITCH .i   GET_ARGUMENTS.  (   GET_PROCINFO1   DO_LOGFILElPC   (DO_NAMEZ (((" DO_NODEID6 $& PARSE_BATCHV$XPARSE_BATCH 21wS   "d |!PROCEDURE$ $DATA$ .DEBUG$ PAS_$WRITELN `VFMT_$WS5 0NAME_$GET_WDIR PM_$GET_SID_TXT PPGM_$GET_ARG  PGM_$EXIT pVFMT_$WS2 @PAS_$WRITE STREAM_$INQUIRE `PAS_$OUTPUT X  &*06:@FJPVZ`fjpvz SHAR_EOF chmod +x 'parse_batch' fi # end of overwriting check if test -f 'batch.install' then echo shar: will not over-write existing file "'batch.install'" else cat << \SHAR_EOF > 'batch.install' von cpf batch /users/userlib/com/batch -r -f -du cpf parse_batch /users/userlib/com/parse_batch -r -f -du cpf sh_log //bert/com/sh_log -r -f -du cpf sh_log //ernie/com/sh_log -r -f -du cpf sh_log //tigger/com/sh_log -r -f -du cpf sh_log //bertha/com/sh_log -r -f -du cpf sh_log //piggy/com/sh_log -r -f -du cpf sh_log //winnie/com/sh_log -r -f -du cpf sh_log //oscar/com/sh_log -r -f -du cpf sh_log //eeyore/com/sh_log -r -f -du cpf batch.hlp //bert/sys/help/batch.hlp -r -f -du cpf batch.hlp //ernie/sys/help/batch.hlp -r -f -du cpf batch.hlp //tigger/sys/help/batch.hlp -r -f -du cpf batch.hlp //bertha/sys/help/batch.hlp -r -f -du cpf batch.hlp //piggy/sys/help/batch.hlp -r -f -du cpf batch.hlp //winnie/sys/help/batch.hlp -r -f -du cpf batch.hlp //oscar/sys/help/batch.hlp -r -f -du cpf batch.hlp //eeyore/sys/help/batch.hlp -r -f -du voff SHAR_EOF chmod +x 'batch.install' fi # end of overwriting check cd .. # End of shell archive exit 0