From a1c8bd2337f1665d43b44da9e0332b954ec0a06e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9rome=20Perrin?= <jerome@nexedi.com> Date: Sun, 11 Jan 2015 11:42:30 +0100 Subject: [PATCH] wrapper script: workaround kernel limitation in shebang line length http://stackoverflow.com/a/10826085 --- slapos/recipe/librecipe/generic.py | 20 +++++++++++++++++--- slapos/recipe/wrapper.py | 15 +++++++++++---- 2 files changed, 28 insertions(+), 7 deletions(-) diff --git a/slapos/recipe/librecipe/generic.py b/slapos/recipe/librecipe/generic.py index 9019abe6f..f56c64760 100644 --- a/slapos/recipe/librecipe/generic.py +++ b/slapos/recipe/librecipe/generic.py @@ -134,13 +134,14 @@ class GenericBaseRecipe(object): pidfile=None ): """ - Creates a very simple (one command) shell script for process replacement. + Creates a shell script for process replacement. Takes care of quoting. + Takes care of #! line limitation when the wrapped command is a script. if pidfile parameter is specified, then it will make the wrapper a singleton, accepting to run only if no other instance is running. """ - lines = [ '#!/bin/sh' ] + lines = [ '#!/bin/bash' ] for comment in comments: lines.append('# %s' % comment) @@ -164,7 +165,20 @@ class GenericBaseRecipe(object): fi echo $$ > $pidfile""" % (pidfile, command))) - lines.append('exec %s' % shlex.quote(command)) + # Inspired by http://stackoverflow.com/a/10826085 + lines.append(dedent("""\ + COMMAND=%s + + # If the wrapped command uses a shebang, execute the referenced + # executable passing the script path as first argument. + # This is to workaround the limitation of 127 characters in #! + if [[ -f $COMMAND && x$(head -c2 "$COMMAND") = x"#!" ]]; then + SHEBANG=$(head -1 "$COMMAND") + INTERPRETER=( ${SHEBANG#\#!} ) + COMMAND="${INTERPRETER[@]} $COMMAND" + fi + + exec $COMMAND """ % shlex.quote(command))) for param in parameters: if len(lines[-1]) < 40: diff --git a/slapos/recipe/wrapper.py b/slapos/recipe/wrapper.py index cb0f1c266..cb1cddb61 100644 --- a/slapos/recipe/wrapper.py +++ b/slapos/recipe/wrapper.py @@ -54,8 +54,15 @@ class Recipe(GenericBaseRecipe): if environment is not None: environment = dict((k.strip(), v.strip()) for k, v in [ line.split('=') for line in environment.splitlines() if line.strip() ]) - return [self.createPythonScript( - wrapper_path, + + # We create a python script and a wrapper around the python + # script because the python script might have a too long #! line + python_script = self.createPythonScript( + wrapper_path+'.py', 'slapos.recipe.librecipe.execute.generic_exec', - (command_line, wait_files, environment,), - )] + (command_line, wait_files, environment,), ) + return [python_script, self.createWrapper( + name=wrapper_path, + command=python_script, + parameters_extra=parameters_extra) ] + -- 2.30.9