natefoo / slurm-drmaa

DRMAA for Slurm: Implementation of the DRMAA C bindings for Slurm
GNU General Public License v3.0
48 stars 22 forks source link

Single quotes in the expanded args should be escaped #31

Open stmlange opened 5 years ago

stmlange commented 5 years ago

Hello, thank you for this library. I noticed a small bug when using single quotes in arguments. I believe that single quotes in the expanded args (https://github.com/natefoo/slurm-drmaa/blob/665d5b5d7deb52534e88fadb434d17350dce1a5a/slurm_drmaa/job.c#L615) should be escaped.

In my case I'm running

bash, "-c", "source /tmp/init.sh ; /bin/sort '-s' '-k' '3' '-t' '\t'" (note I use , to separate the arguments, in total two arguments are passed to bash)

which will then be translated into

d #15300 [     0.06]  * # Script:
d #15300 [     0.06]  | #!/bin/bash
d #15300 [     0.06]  | bash '-c' 'source /tmp/init.sh ; /bin/sort '-s' '-k' '3' '-t' '     ''

However this fails with:

/bin/sort: option requires an argument -- 't'
Try '/bin/sort --help' for more information.

I believe what happens internally is that bash -c treats source /tmp/init.sh ; /bin/sort as the first string and as per documentation everything after becomes an argument:

If the -c option is present, then commands are read from string. If there are arguments after the string, they are assigned to the positional parameters, starting with $0. 

To solve this I believe that the single quotes within the expanded args should be escaped (e.g. via https://creativeandcritical.net/str-replace-c)

======= consider this minimal example:

#!/usr/bin/env python
import drmaa
import os

def main():
    error_log = os.path.join(os.getcwd(), 'error.log')
    with drmaa.Session() as s:
        print('Creating job template')
        jt = s.createJobTemplate()
        jt.remoteCommand = "/bin/bash"
        jt.args = [ '-c', "/bin/sort '-s' '-k' '3' '-t' '\t'" ]

        jt.errorPath = ":" + error_log

        jobid = s.runJob(jt)
        print('Your job has been submitted with ID {0}'.format(jobid))

        retval = s.wait(jobid, drmaa.Session.TIMEOUT_WAIT_FOREVER)
        print('Job: {0} finished with status {1}'.format(retval.jobId, retval.exitStatus))

        with open(error_log, 'r') as fin:
            print(fin.read())

        print('Cleaning up')
        s.deleteJobTemplate(jt)
        os.remove(error_log)

if __name__=='__main__':
    main()

results in

$ python foo.py
Creating job template
Your job has been submitted with ID 7990
Job: 7990 finished with status 2
/bin/sort: option requires an argument -- 't'
Try '/bin/sort --help' for more information.

Cleaning up