Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issue 1079 bash login shell #1502

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .travis-data/code-setup-input.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,6 @@ simple script that doubles a number and sleeps for a given number of seconds
False
simpleplugins.templatereplacer
torquessh
/usr/local/bin/doubler.sh
/usr/local/bin/d"o'ub ler.sh


4 changes: 2 additions & 2 deletions .travis-data/torquessh-doubler/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ MAINTAINER AiiDA Team <info@aiida.net>
# Use baseimage-docker's init system.
CMD ["/sbin/my_init"]

# Install required packages
COPY doubler.sh /usr/local/bin/


# Use messed-up filename to test quoting robustness
RUN mv /usr/local/bin/doubler.sh /usr/local/bin/d\"o\'ub\ ler.sh
5 changes: 5 additions & 0 deletions .travis-data/torquessh-doubler/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,8 @@
This folder contains an example of an extension of the torquessh-base image,
where we add a very basic script to double a number.
This is meant to be a very lightweight 'code' to test daemon functionality.

# Notes

Inside the docker image, we use a filename including single quotes, double
quotes and spaces in order to test the robustness of AiiDA's escaping routines.
20 changes: 14 additions & 6 deletions aiida/transport/plugins/local.py
Original file line number Diff line number Diff line change
Expand Up @@ -704,21 +704,29 @@ def isfile(self, path):

def _exec_command_internal(self, command):
"""
Executes the specified command, first changing directory to the
current working directory as returned by self.getcwd().
Does not wait for the calculation to finish.
Executes the specified command in bash login shell.

Before the command is executed, changes directory to the current
working directory as returned by self.getcwd().

For a higher-level exec_command that automatically waits for the
job to finish, use exec_command_wait.
For executing commands and waiting for them to finish, use
exec_command_wait.
Otherwise, to end the process, use the proc.wait() method.

:param command: the command to execute
:param command: the command to execute. The command is assumed to be
already escaped using :py:func:`aiida.common.utils.escape_for_bash`.

:return: a tuple with (stdin, stdout, stderr, proc),
where stdin, stdout and stderr behave as file-like objects,
proc is the process object as returned by the
subprocess.Popen() class.
"""
from aiida.common.utils import escape_for_bash

# Note: The outer shell will eat one level of escaping, while
# 'bash -l -c ...' will eat another. Thus, we need to escape again.
command = 'bash -l -c ' + escape_for_bash(command)

proc = subprocess.Popen(command, shell=True, stdin=subprocess.PIPE,
stdout=subprocess.PIPE, stderr=subprocess.PIPE,
cwd=self.getcwd())
Expand Down
19 changes: 11 additions & 8 deletions aiida/transport/plugins/ssh.py
Original file line number Diff line number Diff line change
Expand Up @@ -1290,15 +1290,16 @@ def isfile(self,path):

def _exec_command_internal(self,command,combine_stderr=False,bufsize=-1):
"""
Executes the specified command, first changing directory to the
current working directory are returned by
self.getcwd().
Does not wait for the calculation to finish.
Executes the specified command in bash login shell.

Before the command is executed, changes directory to the current
working directory as returned by self.getcwd().

For a higher-level _exec_command_internal that automatically waits for the
job to finish, use exec_command_wait.
For executing commands and waiting for them to finish, use
exec_command_wait.

:param command: the command to execute
:param command: the command to execute. The command is assumed to be
already escaped using :py:func:`aiida.common.utils.escape_for_bash`.
:param combine_stderr: (default False) if True, combine stdout and
stderr on the same buffer (i.e., stdout).
Note: If combine_stderr is True, stderr will always be empty.
Expand All @@ -1324,7 +1325,9 @@ def _exec_command_internal(self,command,combine_stderr=False,bufsize=-1):
self.logger.debug("Command to be executed: {}".format(
command_to_execute))

channel.exec_command(command_to_execute)
# Note: The default shell will eat one level of escaping, while
# 'bash -l -c ...' will eat another. Thus, we need to escape again.
channel.exec_command('bash -l -c ' + escape_for_bash(command_to_execute))

stdin = channel.makefile('wb',bufsize)
stdout = channel.makefile('rb',bufsize)
Expand Down