sempre/fig/bin/qcreate

99 lines
2.2 KiB
Ruby
Executable File

#!/usr/bin/ruby
help = <<EOF
--- qcreate ---
Creates a dedicated "execution" directory to store all the output of a command.
Optional: uses qsub to submit the job.
General usage:
qcreate [-qsub] [-statePath /path/to/state] <command> [<arg> ... <arg>]
All occurrences of _OUTPATH_ in the arguments are replaced with the execution directory.
For example:
qcreate touch _OUTPATH_/foo
will create the file state/execs/<id>.exec/foo, where <id> is unique to this job.
Usage for fig programs:
qcreate java ... -execDir _OUTPATH_ -overwriteExecDir
More generally, _OUTPATH_ will be replaced with the execution directory.
EOF
statePath = 'state'
qsub = false
# Interpret the prefix of ARGV as options to be interpreted.
while true
if ARGV[0] == '-qsub'
ARGV.shift
qsub = true
elsif ARGV[0] == '-statePath'
ARGV.shift
statePath = ARGV.shift
if not statePath
puts "Error: missing statePath"
puts help
exit 1
end
else
break
end
end
if ARGV.size == 0
puts "Error: no command specified"
puts help
exit 1
end
system "mkdir -p #{statePath}/execs" or exit 1
lastExecFile = statePath+"/lastExec"
if not File.exists?(lastExecFile)
puts "Creating #{lastExecFile}"
system "touch #{lastExecFile}"
end
f = File.open(lastExecFile, 'r+')
if f.flock(File::LOCK_EX) != 0
puts "Error: unable to lock #{lastExecFile}"
exit 1
end
id = f.read
begin
id = id == '' ? -1 : Integer(id)
id += 1
f.rewind
f.puts id
f.flush
f.truncate(f.pos)
rescue
puts "Error: #{lastExecFile} has '#{id}' which is not an integer"
id = nil
end
f.close
exit 1 if not id
execPath = statePath + "/execs/#{id}.exec"
puts "Execution directory: #{execPath}"
if not Dir.mkdir(execPath)
puts "Already exists (this shouldn't happen): #{execPath}"
exit 1
end
cmdFile = "#{execPath}/#{id}.sh"
out = open(cmdFile, 'w')
cmd = ARGV.map{|x| x =~ /[ "]/ ? x.inspect : x}.join(' ').gsub(/_OUTPATH_/, execPath)
cmd += " > #{execPath}/stdout 2> #{execPath}/stderr" if qsub
out.puts "#!/bin/bash"
out.puts "cd #{Dir.pwd}"
out.puts cmd
out.close
puts cmd
system "git rev-parse HEAD > #{execPath}/git-hash" if File.exists?('.git')
if qsub
exec("qsub #{File.expand_path(cmdFile)} -o /dev/null -e /dev/null")
else
exec("bash #{File.expand_path(cmdFile)}")
end