Skip to content
Closed
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
17 changes: 17 additions & 0 deletions Doc/library/subprocess.rst
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,20 @@ underlying :class:`Popen` interface can be used directly.
*stdout* and *stderr* attributes added


.. function:: shell(cmd, **kwargs)

Run a shell command. Wait for command to complete, then return a
:class:`CompletedProcess` instance.

The *cmd* must be a :class:`str`.

See the :func:`run` function documentation for optional parameters.

Read the `Security Considerations`_ section before using this function.

.. versionadded:: 3.14


.. _frequently-used-arguments:

Frequently Used Arguments
Expand Down Expand Up @@ -764,6 +778,9 @@ quoted appropriately to avoid
vulnerabilities. On :ref:`some platforms <shlex-quote-warning>`, it is possible
to use :func:`shlex.quote` for this escaping.

The functions :func:`shell` and :func:`getstatusoutput` always use
``shell=True``.

On Windows, batch files (:file:`*.bat` or :file:`*.cmd`) may be launched by the
operating system in a system shell regardless of the arguments passed to this
library. This could result in arguments being parsed according to shell rules,
Expand Down
8 changes: 8 additions & 0 deletions Doc/whatsnew/3.14.rst
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,14 @@ pathlib
another.
(Contributed by Barney Gale in :gh:`73991`.)

subprocess
----------

* Add :func:`subprocess.shell` function to run a shell command.
Read the :ref:`Security Considerations <subprocess-security>` section before
using this function.
(Contributed by Victor Stinner in :gh:`120952`.)

symtable
--------

Expand Down
18 changes: 17 additions & 1 deletion Lib/subprocess.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@

__all__ = ["Popen", "PIPE", "STDOUT", "call", "check_call", "getstatusoutput",
"getoutput", "check_output", "run", "CalledProcessError", "DEVNULL",
"SubprocessError", "TimeoutExpired", "CompletedProcess"]
"SubprocessError", "TimeoutExpired", "CompletedProcess", "shell"]
# NOTE: We intentionally exclude list2cmdline as it is
# considered an internal implementation detail. issue10838.

Expand Down Expand Up @@ -2221,3 +2221,19 @@ def kill(self):
"""Kill the process with SIGKILL
"""
self.send_signal(signal.SIGKILL)


def shell(cmd, **kwargs):
"""
Run a shell command.

Read the Security Considerations section of the documentation before using
this function.
"""
if not kwargs.pop('shell', True):
raise ValueError("the 'shell' argument must be True or unspecified")

if not isinstance(cmd, str):
raise TypeError("cmd type must be str")

return run(cmd, shell=True, **kwargs)
16 changes: 16 additions & 0 deletions Lib/test/test_subprocess.py
Original file line number Diff line number Diff line change
Expand Up @@ -1824,6 +1824,22 @@ def test_encoding_warning(self):
self.assertTrue(lines[0].startswith(b"<string>:2: EncodingWarning: "))
self.assertTrue(lines[2].startswith(b"<string>:3: EncodingWarning: "))

def test_shell(self):
# Test basic echo command
proc = subprocess.shell("echo Python", stdout=subprocess.PIPE, text=True)
self.assertEqual(proc.returncode, 0)
self.assertEqual(proc.stdout.rstrip(), "Python")

# cmd type must be str
with self.assertRaises(TypeError):
subprocess.shell(b"echo Python")
with self.assertRaises(TypeError):
subprocess.shell(["echo", "Python"])

# Passing shell=False is invalid
with self.assertRaises(ValueError):
subprocess.shell("echo Python", shell=False)


def _get_test_grp_name():
for name_group in ('staff', 'nogroup', 'grp', 'nobody', 'nfsnobody'):
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Add :func:`subprocess.shell` function to run a shell command. Read the
:ref:`Security Considerations <subprocess-security>` section before using
this function. Patch by Victor Stinner.