Rush - Submit Scripts
(C) Copyright 1995,2000 Greg Ercolano. All rights reserved.
V 102.41 03/05/04
Strikeout text indicates features not yet implemented

  Submit Scripts  
 Template Submit Scripts
    In order to submit a job using the templates, you need both a submit script and render script. Both can be created quickly from scratch using the stock templates. A template submit script can be created quickly via:
    	      rush -tss > submit-script 
    	
    Here's a template submit script written in CSH:

      Csh Template Script
      #!/bin/csh -f
      
      #
      #  S U B M I T
      #
      
      source $RUSH_DIR/etc/.submit
      rush -submit << EOF
          title       SHOW/SHOT
          ram         250
          frames      1-100
          logdir      $cwd/logs     # "-" to disable
          command     $cwd/render-script
          autodump    done          # off, done, donefail
          cpus        vaio=1@100
      
          # Optional
          #donemail   you@foo.com   # "-" to disable
          #notes      This is a test
          #state      Pause
          #logflags   keepall
          #frames     1-10=Hold:Hello_world
          #criteria   ( linux | irix | osf1 )
      EOF
      
      exit $status
              

    Submit scripts don't have to be written as csh scripts. Any language that can pipe text into a command can be used to submit jobs. The following shows a template submit script written in Perl:

      Perl Template Submit
      #!/usr/bin/perl
      
      my $me   = `logname`; chomp($me);
      my $pwd  = `pwd`;     chomp($pwd);
      
      open(SUBMIT, "|rush -submit");
      print SUBMIT <<"EOF";
          title      mytest
          ram        10
          frames     1-100
          logdir     $pwd/logs
          command    $pwd/render-script 
          donemail   $me
          autodump   off
          criteria   ( linux | irix )
          cpus       +any=10\@100
      EOF
      close(SUBMIT);
      
      if ( $? >> 8 ) 
          { print STDERR "-- submit failed --\n"; exit(1); }
      
      exit(0);
              

    And the same program written in C:

      C Template Submit Script
      
      #include <stdio.h>
      #include <unistd.h>
      
      /* C EXAMPLE: Template Submit
       *
       *        UNIX COMPILE: 
       *             cc renderit.c -o renderit
       *
       *     WINDOWS COMPILE:
       *             vcvars32
       *             cl renderit.c
       */
      
      #ifdef _WIN32
      #include <direct.h>
      #define popen  		_popen 
      #define pclose 		_pclose 
      #endif
      
      int main(int argc, char *argv[])
      {
          char *me = getlogin();
          char cwd[1024]; getcwd(cwd, 1023);
      
          if ( ( fp = popen("rush -submit", "w") ) == NULL )
      	{ perror("couldn't popen(rush -submit)"); exit(1); }
      
          fprintf(fp, "    title      mytest\n"
                      "    ram        10\n"
                      "    frames     1-100\n"
                      "    logdir     $pwd/logs\n"
                      "    command    $pwd/renderit\n"
                      "    donemail   $me\n"
                      "    autodump   off\n"
                      "    criteria   ( linux | irix )\n"
                      "    cpus       +any=10@100\n");
      
          if ( pclose(fp) != 0 )
              { return(1); }
      
          return(0);
      }
              




 Perl: Submit Script, Read Back Jobid

    Here's a perl script that submits a sleep job, and parses back the jobid into a variable, which the perl script can then use for other purposes.

      Perl Submit and Read Back Jobid
      #!/usr/bin/perl
      
      # Create rush submit file
      my $tmp = "/tmp/.submit.$$";
      unless ( open ( SUBMIT, ">$tmp" ) ) 
          { print "open(>$tmp): $!\n"; exit(1); }
      
      print SUBMIT <<"EOF";
          title   SHOW/SHOT
          frames  1-10
          command sleep 30
          cpus    +any=1
      EOF
      
      unless ( close( SUBMIT ) )
          { print "close($tmp): $!\n"; exit(1); }
      
      # Submit the job, parse out jobid
      my $out = `rush -submit < $tmp`; unlink ( $tmp );
      if ( $out =~ /RUSH_JOBID (\S+)/ ) { $ENV{RUSH_JOBID} = $1; }
      else { print STDERR "$out\nSubmit failed.\n"; exit(1); }
      
      print "RUSH_JOBID IS NOW $ENV{RUSH_JOBID}\n";
      exit(0);
              




    Here's a simple C program that submits a sleep job.

      C Programming Example: Simple Submit
      #include <stdio.h>
      main()
      {
          FILE *fp;
          if ( ( fp = fopen("my-submit", "w") ) == NULL )
              { perror("my-submit"); exit(1); }
          fprintf(fp, "title      TEST\n"
                      "ram        1\n"
                      "frames     1-10\n"
                      "command    rush -sleep 300\n"
                      "cpus       +any=10\n");
          fclose(fp);
          system("rush -submit < my-submit");
      }
              




    Here's a more complex C program that acts as both a submit and render script, using recursion to invoke itself. It also uses pipes to prevent creating the temporary file used to submit the job in the previous example. Note that it's critical to invoke this program with an absolute path so the program can invoke itself correctly from other machines.

    There are three versions of this program:

      C Programming Example: Submit and Render
      #include <stdio.h>
      #include <stdlib.h>
      #include <string.h>
      #include <errno.h>
      
      /* C EXAMPLE: Submit and Render
       *
       * This program acts as both a submit and render script.
       * It is important to invoke this program initially with an absolute path,
       * so the program can call itself correctly from other machines.
       *
       *        UNIX COMPILE: 
       *             cc filename.c -o filename
       *
       *     WINDOWS COMPILE:
       *             vcvars32
       *             cl filename.c
       */
      #ifdef _WIN32
      #include <direct.h>
      #define popen  		_popen 
      #define pclose 		_pclose 
      #define mkdir(a,b)	_mkdir(a)
      #endif
      
      int main(int argc, char **argv)
      {
          if ( argc >= 2 && strcmp(argv[1], "-render") == 0 )
          {
      	/* CALLED AS A RENDER SCRIPT? 
      	 * Invoke maya, return exit code.
      	 */
      	int t;
      	char cmd[4096];
      
      	sprintf(cmd, "mayabatch -render -s %s -e %s",
      	    getenv("RUSH_FRAME"),
      	    getenv("RUSH_FRAME"));
      	for ( t=2; t<argc; t++ )
      	    { strcat(cmd, " "); strcat(cmd, argv[t]); }
      
      	fprintf(stderr, "Executing: %s\n", cmd);
      	t = system(cmd) >> 8;
      	if ( t != 0 )
      	    { fprintf(stderr, "MAYA FAILED: EXIT CODE=%d\n", t); exit(1); }
      
      	fprintf(stderr, "MAYA SUCCESS\n");
      	exit(0);
          }
          else
          {
      	/* CALLED AS A SUBMIT SCRIPT?
      	 * Then prompt for info, and submit the job
      	 */
      	FILE *fp;
      	char title[40];
      	char frames[40];
      	char scene[1024];
      	char cpus[1024];
      	char cmd[1024];
      	char logdir[1024];
      
      	fprintf(stderr, "  Enter title for job: "); 
      	fgets(title, sizeof(title)-1, stdin);
      	title[strlen(title)-1] = '\0';
      
      	fprintf(stderr, " Enter the scene file: "); 
      	fgets(scene, sizeof(scene)-1, stdin);
      	scene[strlen(scene)-1] = '\0';
      
      	fprintf(stderr, "Enter the frame range: "); 
      	fgets(frames, sizeof(frames)-1, stdin);
      	frames[strlen(frames)-1] = '\0';
      
      	fprintf(stderr, "       Enter the cpus: "); 
      	fgets(cpus, sizeof(cpus)-1, stdin);
      	cpus[strlen(cpus)-1] = '\0';
      
      	/* MAKE LOGDIR BASED ON TITLE OF JOB
      	 * There are cleaner ways to do this.
      	 */
       	{
      	    int oldmask = umask(0);
      	    sprintf(logdir, "//tahoe/net/tmp/%s", title);
      	    if ( mkdir(logdir, 0777) < 0 && errno != EEXIST )
      		{ perror(logdir); exit(1); }
      	    umask(oldmask);
      	}
      
      	/* SUBMIT THE JOB 
      	 * Feed the submit commands down a pipe.
      	 */
      	if ( ( fp = popen("rush -submit", "w") ) == NULL )
      	    { perror("couldn't popen(rush -submit)"); exit(1); }
      	fprintf(fp, "title   %s\n", title);
      	fprintf(fp, "ram     1\n");
      	fprintf(fp, "frames  %s\n", frames);
      	fprintf(fp, "logdir  %s\n", logdir);
      	fprintf(fp, "command %s -render %s\n", argv[0], scene);
      	fprintf(fp, "cpus    %s\n", cpus);
      	pclose(fp);
      
      	exit(0);
          }
          /*NOTREACHED*/
      }
              

      Perl: Submit and Render Script
      #!/usr/bin/perl
      
      # PERL EXAMPLE: Submit and Render
      #
      # This program acts as both a submit and render script.
      # It is important to invoke this program initially with an absolute path,
      # so the program can call itself correctly from other machines.
      #
      
      $|=1;
      if ( $ARGV[0] eq "-render" )
      {
          # CALLED AS A RENDER SCRIPT?
          # Invoke maya, return exit code.
          my $t;
          my $cmd = sprintf("mayabatch -render -s %s -e %s",
                             $ENV{RUSH_FRAME},
                             $ENV{RUSH_FRAME});
      
          for ( $t=1; $t<=$#ARGV; $t++ )
              { $cmd .= " $ARGV[$t]"; }
      
          print STDERR "Executing: $cmd\n";
          $t = system($cmd) >> 8;
          if ( $t != 0 )
              { print STDERR "MAYA FAILED: EXIT CODE=$t\n"; exit(1); }
      
          print STDERR "MAYA SUCCESS\n";
          exit(0);
      }
      else
      {
          # CALLED AS A SUBMIT SCRIPT?
          # Then prompt for info, and submit the job
      
          print STDERR "  Enter title for job: ";
          my $title = <STDIN>; chomp($title);
      
          print STDERR " Enter the scene file: ";
          my $scene = <STDIN>; chomp($scene);
      
          print STDERR "Enter the frame range: ";
          my $frames = <STDIN>; chomp($frames);
      
          print STDERR "       Enter the cpus: ";
          my $cpus = <STDIN>; chomp($cpus);
      
          # MAKE LOGDIR BASED ON TITLE OF JOB
          # There are cleaner ways to do this
          #
          my $logdir = sprintf("//tahoe/net/tmp/%s", $title);
          if ( ! -e $logdir )
          {
              my $oldmask = umask(0);
      	unless ( mkdir($logdir, 0777) )
      	    { print STDERR "$logdir: $!\n"; exit(1); }
              umask($oldmask);
          }
      
          # SUBMIT THE JOB
          # Feed the submit commands down a pipe.
          #
          open(SUBMIT, "|rush -submit");
          print SUBMIT <<"EOF";
          title      $title
          ram        1
          frames     $frames
          logdir     $logdir
          command    perl $0 -render $scene
          cpus       $cpus
      EOF
          close(SUBMIT);
      
          if ( $? >> 8 ) 
      	{ print STDERR "-- submit failed --\n"; exit(1); }
      
          exit(0);
      }
              

      CSH: Submit and Render Script
      #!/bin/csh -f
      
      # CSH EXAMPLE: Submit and Render
      #
      # This program acts as both a submit and render script.
      # It is important to invoke this program initially with an absolute path,
      # so the program can call itself correctly from other machines.
      #
      
      if ( "$1" == "-render" ) then
      
          # CALLED AS A RENDER SCRIPT?
          # Invoke maya, return exit code.
      
          set cmd = "mayabatch -render -s $RUSH_FRAME -e $RUSH_FRAME";
      
          shift
          set cmd = "$cmd $*:q"
      
          echo "Executing: $cmd"
          $cmd
          set err = $status
          if ( $err != 0 ) then
              echo "MAYA FAILED: EXIT CODE=$err\n"
      	exit 1
          endif
      
          echo "MAYA SUCCESS"
          exit 0
      else
          # CALLED AS A SUBMIT SCRIPT?
          # Then prompt for info, and submit the job
      
          echo -n "  Enter title for job: ";
          set title = "$<"
      
          echo " Enter the scene file: ";
          set scene = "$<"
      
          echo "Enter the frame range: ";
          set frames = "$<"
      
          echo "       Enter the cpus: ";
          set cpus = "$<"
      
          # MAKE LOGDIR BASED ON TITLE OF JOB
          # There are cleaner ways to do this
          #
          set logdir = "//tahoe/net/tmp/$title"
          if ( ! -e $logdir ) then
              umask 0
      	mkdir -m 0777 $logdir
      	if ( $status ) exit 1
          endif
      
          # SUBMIT THE JOB
          # Feed the submit commands down a pipe.
          #
          cat << EOF | rush -submit
          title      $title
          ram        1
          frames     $frames
          logdir     $logdir
          command    csh -f $0 -render $scene
          cpus       $cpus
      EOF
          exit $status
      endif