operations.py 52 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295
  1. """
  2. Functions to be used in fabfiles and other non-core code, such as run()/sudo().
  3. """
  4. from __future__ import with_statement
  5. import errno
  6. import os
  7. import os.path
  8. import posixpath
  9. import re
  10. import subprocess
  11. import sys
  12. import time
  13. from glob import glob
  14. from contextlib import closing, contextmanager
  15. from fabric.context_managers import (settings, char_buffered, hide,
  16. quiet as quiet_manager, warn_only as warn_only_manager)
  17. from fabric.io import output_loop, input_loop
  18. from fabric.network import needs_host, ssh, ssh_config
  19. from fabric.sftp import SFTP
  20. from fabric.state import env, connections, output, win32, default_channel
  21. from fabric.thread_handling import ThreadHandler
  22. from fabric.utils import (
  23. abort, error, handle_prompt_abort, indent, _pty_size, warn, apply_lcwd,
  24. RingBuffer,
  25. )
  26. def _shell_escape(string):
  27. """
  28. Escape double quotes, backticks and dollar signs in given ``string``.
  29. For example::
  30. >>> _shell_escape('abc$')
  31. 'abc\\\\$'
  32. >>> _shell_escape('"')
  33. '\\\\"'
  34. """
  35. for char in ('"', '$', '`'):
  36. string = string.replace(char, '\%s' % char)
  37. return string
  38. class _AttributeString(str):
  39. """
  40. Simple string subclass to allow arbitrary attribute access.
  41. """
  42. @property
  43. def stdout(self):
  44. return str(self)
  45. class _AttributeList(list):
  46. """
  47. Like _AttributeString, but for lists.
  48. """
  49. pass
  50. # Can't wait till Python versions supporting 'def func(*args, foo=bar)' become
  51. # widespread :(
  52. def require(*keys, **kwargs):
  53. """
  54. Check for given keys in the shared environment dict and abort if not found.
  55. Positional arguments should be strings signifying what env vars should be
  56. checked for. If any of the given arguments do not exist, Fabric will abort
  57. execution and print the names of the missing keys.
  58. The optional keyword argument ``used_for`` may be a string, which will be
  59. printed in the error output to inform users why this requirement is in
  60. place. ``used_for`` is printed as part of a string similar to::
  61. "Th(is|ese) variable(s) (are|is) used for %s"
  62. so format it appropriately.
  63. The optional keyword argument ``provided_by`` may be a list of functions or
  64. function names or a single function or function name which the user should
  65. be able to execute in order to set the key or keys; it will be included in
  66. the error output if requirements are not met.
  67. Note: it is assumed that the keyword arguments apply to all given keys as a
  68. group. If you feel the need to specify more than one ``used_for``, for
  69. example, you should break your logic into multiple calls to ``require()``.
  70. .. versionchanged:: 1.1
  71. Allow iterable ``provided_by`` values instead of just single values.
  72. """
  73. # If all keys exist and are non-empty, we're good, so keep going.
  74. missing_keys = filter(lambda x: x not in env or (x in env and
  75. isinstance(env[x], (dict, list, tuple, set)) and not env[x]), keys)
  76. if not missing_keys:
  77. return
  78. # Pluralization
  79. if len(missing_keys) > 1:
  80. variable = "variables were"
  81. used = "These variables are"
  82. else:
  83. variable = "variable was"
  84. used = "This variable is"
  85. # Regardless of kwargs, print what was missing. (Be graceful if used outside
  86. # of a command.)
  87. if 'command' in env:
  88. prefix = "The command '%s' failed because the " % env.command
  89. else:
  90. prefix = "The "
  91. msg = "%sfollowing required environment %s not defined:\n%s" % (
  92. prefix, variable, indent(missing_keys)
  93. )
  94. # Print used_for if given
  95. if 'used_for' in kwargs:
  96. msg += "\n\n%s used for %s" % (used, kwargs['used_for'])
  97. # And print provided_by if given
  98. if 'provided_by' in kwargs:
  99. funcs = kwargs['provided_by']
  100. # non-iterable is given, treat it as a list of this single item
  101. if not hasattr(funcs, '__iter__'):
  102. funcs = [funcs]
  103. if len(funcs) > 1:
  104. command = "one of the following commands"
  105. else:
  106. command = "the following command"
  107. to_s = lambda obj: getattr(obj, '__name__', str(obj))
  108. provided_by = [to_s(obj) for obj in funcs]
  109. msg += "\n\nTry running %s prior to this one, to fix the problem:\n%s"\
  110. % (command, indent(provided_by))
  111. abort(msg)
  112. def prompt(text, key=None, default='', validate=None):
  113. """
  114. Prompt user with ``text`` and return the input (like ``raw_input``).
  115. A single space character will be appended for convenience, but nothing
  116. else. Thus, you may want to end your prompt text with a question mark or a
  117. colon, e.g. ``prompt("What hostname?")``.
  118. If ``key`` is given, the user's input will be stored as ``env.<key>`` in
  119. addition to being returned by `prompt`. If the key already existed in
  120. ``env``, its value will be overwritten and a warning printed to the user.
  121. If ``default`` is given, it is displayed in square brackets and used if the
  122. user enters nothing (i.e. presses Enter without entering any text).
  123. ``default`` defaults to the empty string. If non-empty, a space will be
  124. appended, so that a call such as ``prompt("What hostname?",
  125. default="foo")`` would result in a prompt of ``What hostname? [foo]`` (with
  126. a trailing space after the ``[foo]``.)
  127. The optional keyword argument ``validate`` may be a callable or a string:
  128. * If a callable, it is called with the user's input, and should return the
  129. value to be stored on success. On failure, it should raise an exception
  130. with an exception message, which will be printed to the user.
  131. * If a string, the value passed to ``validate`` is used as a regular
  132. expression. It is thus recommended to use raw strings in this case. Note
  133. that the regular expression, if it is not fully matching (bounded by
  134. ``^`` and ``$``) it will be made so. In other words, the input must fully
  135. match the regex.
  136. Either way, `prompt` will re-prompt until validation passes (or the user
  137. hits ``Ctrl-C``).
  138. .. note::
  139. `~fabric.operations.prompt` honors :ref:`env.abort_on_prompts
  140. <abort-on-prompts>` and will call `~fabric.utils.abort` instead of
  141. prompting if that flag is set to ``True``. If you want to block on user
  142. input regardless, try wrapping with
  143. `~fabric.context_managers.settings`.
  144. Examples::
  145. # Simplest form:
  146. environment = prompt('Please specify target environment: ')
  147. # With default, and storing as env.dish:
  148. prompt('Specify favorite dish: ', 'dish', default='spam & eggs')
  149. # With validation, i.e. requiring integer input:
  150. prompt('Please specify process nice level: ', key='nice', validate=int)
  151. # With validation against a regular expression:
  152. release = prompt('Please supply a release name',
  153. validate=r'^\w+-\d+(\.\d+)?$')
  154. # Prompt regardless of the global abort-on-prompts setting:
  155. with settings(abort_on_prompts=False):
  156. prompt('I seriously need an answer on this! ')
  157. """
  158. handle_prompt_abort("a user-specified prompt() call")
  159. # Store previous env value for later display, if necessary
  160. if key:
  161. previous_value = env.get(key)
  162. # Set up default display
  163. default_str = ""
  164. if default != '':
  165. default_str = " [%s] " % str(default).strip()
  166. else:
  167. default_str = " "
  168. # Construct full prompt string
  169. prompt_str = text.strip() + default_str
  170. # Loop until we pass validation
  171. value = None
  172. while value is None:
  173. # Get input
  174. value = raw_input(prompt_str) or default
  175. # Handle validation
  176. if validate:
  177. # Callable
  178. if callable(validate):
  179. # Callable validate() must raise an exception if validation
  180. # fails.
  181. try:
  182. value = validate(value)
  183. except Exception, e:
  184. # Reset value so we stay in the loop
  185. value = None
  186. print("Validation failed for the following reason:")
  187. print(indent(e.message) + "\n")
  188. # String / regex must match and will be empty if validation fails.
  189. else:
  190. # Need to transform regex into full-matching one if it's not.
  191. if not validate.startswith('^'):
  192. validate = r'^' + validate
  193. if not validate.endswith('$'):
  194. validate += r'$'
  195. result = re.findall(validate, value)
  196. if not result:
  197. print("Regular expression validation failed: '%s' does not match '%s'\n" % (value, validate))
  198. # Reset value so we stay in the loop
  199. value = None
  200. # At this point, value must be valid, so update env if necessary
  201. if key:
  202. env[key] = value
  203. # Print warning if we overwrote some other value
  204. if key and previous_value is not None and previous_value != value:
  205. warn("overwrote previous env variable '%s'; used to be '%s', is now '%s'." % (
  206. key, previous_value, value
  207. ))
  208. # And return the value, too, just in case someone finds that useful.
  209. return value
  210. @needs_host
  211. def put(local_path=None, remote_path=None, use_sudo=False,
  212. mirror_local_mode=False, mode=None, use_glob=True, temp_dir=""):
  213. """
  214. Upload one or more files to a remote host.
  215. As with the OpenSSH ``sftp`` program, `.put` will overwrite pre-existing
  216. remote files without requesting confirmation.
  217. `~fabric.operations.put` returns an iterable containing the absolute file
  218. paths of all remote files uploaded. This iterable also exhibits a
  219. ``.failed`` attribute containing any local file paths which failed to
  220. upload (and may thus be used as a boolean test.) You may also check
  221. ``.succeeded`` which is equivalent to ``not .failed``.
  222. ``local_path`` may be a relative or absolute local file or directory path,
  223. and may contain shell-style wildcards, as understood by the Python ``glob``
  224. module (give ``use_glob=False`` to disable this behavior). Tilde expansion
  225. (as implemented by ``os.path.expanduser``) is also performed.
  226. ``local_path`` may alternately be a file-like object, such as the result of
  227. ``open('path')`` or a ``StringIO`` instance.
  228. .. note::
  229. In this case, `~fabric.operations.put` will attempt to read the entire
  230. contents of the file-like object by rewinding it using ``seek`` (and
  231. will use ``tell`` afterwards to preserve the previous file position).
  232. ``remote_path`` may also be a relative or absolute location, but applied to
  233. the remote host. Relative paths are relative to the remote user's home
  234. directory, but tilde expansion (e.g. ``~/.ssh/``) will also be performed if
  235. necessary.
  236. An empty string, in either path argument, will be replaced by the
  237. appropriate end's current working directory.
  238. While the SFTP protocol (which `put` uses) has no direct ability to upload
  239. files to locations not owned by the connecting user, you may specify
  240. ``use_sudo=True`` to work around this. When set, this setting causes `put`
  241. to upload the local files to a temporary location on the remote end
  242. (defaults to remote user's ``$HOME``; this may be overridden via
  243. ``temp_dir``), and then use `sudo` to move them to ``remote_path``.
  244. In some use cases, it is desirable to force a newly uploaded file to match
  245. the mode of its local counterpart (such as when uploading executable
  246. scripts). To do this, specify ``mirror_local_mode=True``.
  247. Alternately, you may use the ``mode`` kwarg to specify an exact mode, in
  248. the same vein as ``os.chmod``, such as an exact octal number (``0755``) or
  249. a string representing one (``"0755"``).
  250. `~fabric.operations.put` will honor `~fabric.context_managers.cd`, so
  251. relative values in ``remote_path`` will be prepended by the current remote
  252. working directory, if applicable. Thus, for example, the below snippet
  253. would attempt to upload to ``/tmp/files/test.txt`` instead of
  254. ``~/files/test.txt``::
  255. with cd('/tmp'):
  256. put('/path/to/local/test.txt', 'files')
  257. Use of `~fabric.context_managers.lcd` will affect ``local_path`` in the
  258. same manner.
  259. Examples::
  260. put('bin/project.zip', '/tmp/project.zip')
  261. put('*.py', 'cgi-bin/')
  262. put('index.html', 'index.html', mode=0755)
  263. .. note::
  264. If a file-like object such as StringIO has a ``name`` attribute, that
  265. will be used in Fabric's printed output instead of the default
  266. ``<file obj>``
  267. .. versionchanged:: 1.0
  268. Now honors the remote working directory as manipulated by
  269. `~fabric.context_managers.cd`, and the local working directory as
  270. manipulated by `~fabric.context_managers.lcd`.
  271. .. versionchanged:: 1.0
  272. Now allows file-like objects in the ``local_path`` argument.
  273. .. versionchanged:: 1.0
  274. Directories may be specified in the ``local_path`` argument and will
  275. trigger recursive uploads.
  276. .. versionchanged:: 1.0
  277. Return value is now an iterable of uploaded remote file paths which
  278. also exhibits the ``.failed`` and ``.succeeded`` attributes.
  279. .. versionchanged:: 1.5
  280. Allow a ``name`` attribute on file-like objects for log output
  281. .. versionchanged:: 1.7
  282. Added ``use_glob`` option to allow disabling of globbing.
  283. """
  284. # Handle empty local path
  285. local_path = local_path or os.getcwd()
  286. # Test whether local_path is a path or a file-like object
  287. local_is_path = not (hasattr(local_path, 'read') \
  288. and callable(local_path.read))
  289. ftp = SFTP(env.host_string)
  290. with closing(ftp) as ftp:
  291. home = ftp.normalize('.')
  292. # Empty remote path implies cwd
  293. remote_path = remote_path or home
  294. # Expand tildes
  295. if remote_path.startswith('~'):
  296. remote_path = remote_path.replace('~', home, 1)
  297. # Honor cd() (assumes Unix style file paths on remote end)
  298. if not os.path.isabs(remote_path) and env.get('cwd'):
  299. remote_path = env.cwd.rstrip('/') + '/' + remote_path
  300. if local_is_path:
  301. # Apply lcwd, expand tildes, etc
  302. local_path = os.path.expanduser(local_path)
  303. local_path = apply_lcwd(local_path, env)
  304. if use_glob:
  305. # Glob local path
  306. names = glob(local_path)
  307. else:
  308. # Check if file exists first so ValueError gets raised
  309. if os.path.exists(local_path):
  310. names = [local_path]
  311. else:
  312. names = []
  313. else:
  314. names = [local_path]
  315. # Make sure local arg exists
  316. if local_is_path and not names:
  317. err = "'%s' is not a valid local path or glob." % local_path
  318. raise ValueError(err)
  319. # Sanity check and wierd cases
  320. if ftp.exists(remote_path):
  321. if local_is_path and len(names) != 1 and not ftp.isdir(remote_path):
  322. raise ValueError("'%s' is not a directory" % remote_path)
  323. # Iterate over all given local files
  324. remote_paths = []
  325. failed_local_paths = []
  326. for lpath in names:
  327. try:
  328. if local_is_path and os.path.isdir(lpath):
  329. p = ftp.put_dir(lpath, remote_path, use_sudo,
  330. mirror_local_mode, mode, temp_dir)
  331. remote_paths.extend(p)
  332. else:
  333. p = ftp.put(lpath, remote_path, use_sudo, mirror_local_mode,
  334. mode, local_is_path, temp_dir)
  335. remote_paths.append(p)
  336. except Exception, e:
  337. msg = "put() encountered an exception while uploading '%s'"
  338. failure = lpath if local_is_path else "<StringIO>"
  339. failed_local_paths.append(failure)
  340. error(message=msg % lpath, exception=e)
  341. ret = _AttributeList(remote_paths)
  342. ret.failed = failed_local_paths
  343. ret.succeeded = not ret.failed
  344. return ret
  345. @needs_host
  346. def get(remote_path, local_path=None, use_sudo=False, temp_dir=""):
  347. """
  348. Download one or more files from a remote host.
  349. `~fabric.operations.get` returns an iterable containing the absolute paths
  350. to all local files downloaded, which will be empty if ``local_path`` was a
  351. StringIO object (see below for more on using StringIO). This object will
  352. also exhibit a ``.failed`` attribute containing any remote file paths which
  353. failed to download, and a ``.succeeded`` attribute equivalent to ``not
  354. .failed``.
  355. ``remote_path`` is the remote file or directory path to download, which may
  356. contain shell glob syntax, e.g. ``"/var/log/apache2/*.log"``, and will have
  357. tildes replaced by the remote home directory. Relative paths will be
  358. considered relative to the remote user's home directory, or the current
  359. remote working directory as manipulated by `~fabric.context_managers.cd`.
  360. If the remote path points to a directory, that directory will be downloaded
  361. recursively.
  362. ``local_path`` is the local file path where the downloaded file or files
  363. will be stored. If relative, it will honor the local current working
  364. directory as manipulated by `~fabric.context_managers.lcd`. It may be
  365. interpolated, using standard Python dict-based interpolation, with the
  366. following variables:
  367. * ``host``: The value of ``env.host_string``, eg ``myhostname`` or
  368. ``user@myhostname-222`` (the colon between hostname and port is turned
  369. into a dash to maximize filesystem compatibility)
  370. * ``dirname``: The directory part of the remote file path, e.g. the
  371. ``src/projectname`` in ``src/projectname/utils.py``.
  372. * ``basename``: The filename part of the remote file path, e.g. the
  373. ``utils.py`` in ``src/projectname/utils.py``
  374. * ``path``: The full remote path, e.g. ``src/projectname/utils.py``.
  375. While the SFTP protocol (which `get` uses) has no direct ability to download
  376. files from locations not owned by the connecting user, you may specify
  377. ``use_sudo=True`` to work around this. When set, this setting allows `get`
  378. to copy (using sudo) the remote files to a temporary location on the remote end
  379. (defaults to remote user's ``$HOME``; this may be overridden via ``temp_dir``),
  380. and then download them to ``local_path``.
  381. .. note::
  382. When ``remote_path`` is an absolute directory path, only the inner
  383. directories will be recreated locally and passed into the above
  384. variables. So for example, ``get('/var/log', '%(path)s')`` would start
  385. writing out files like ``apache2/access.log``,
  386. ``postgresql/8.4/postgresql.log``, etc, in the local working directory.
  387. It would **not** write out e.g. ``var/log/apache2/access.log``.
  388. Additionally, when downloading a single file, ``%(dirname)s`` and
  389. ``%(path)s`` do not make as much sense and will be empty and equivalent
  390. to ``%(basename)s``, respectively. Thus a call like
  391. ``get('/var/log/apache2/access.log', '%(path)s')`` will save a local
  392. file named ``access.log``, not ``var/log/apache2/access.log``.
  393. This behavior is intended to be consistent with the command-line
  394. ``scp`` program.
  395. If left blank, ``local_path`` defaults to ``"%(host)s/%(path)s"`` in order
  396. to be safe for multi-host invocations.
  397. .. warning::
  398. If your ``local_path`` argument does not contain ``%(host)s`` and your
  399. `~fabric.operations.get` call runs against multiple hosts, your local
  400. files will be overwritten on each successive run!
  401. If ``local_path`` does not make use of the above variables (i.e. if it is a
  402. simple, explicit file path) it will act similar to ``scp`` or ``cp``,
  403. overwriting pre-existing files if necessary, downloading into a directory
  404. if given (e.g. ``get('/path/to/remote_file.txt', 'local_directory')`` will
  405. create ``local_directory/remote_file.txt``) and so forth.
  406. ``local_path`` may alternately be a file-like object, such as the result of
  407. ``open('path', 'w')`` or a ``StringIO`` instance.
  408. .. note::
  409. Attempting to `get` a directory into a file-like object is not valid
  410. and will result in an error.
  411. .. note::
  412. This function will use ``seek`` and ``tell`` to overwrite the entire
  413. contents of the file-like object, in order to be consistent with the
  414. behavior of `~fabric.operations.put` (which also considers the entire
  415. file). However, unlike `~fabric.operations.put`, the file pointer will
  416. not be restored to its previous location, as that doesn't make as much
  417. sense here and/or may not even be possible.
  418. .. note::
  419. If a file-like object such as StringIO has a ``name`` attribute, that
  420. will be used in Fabric's printed output instead of the default
  421. ``<file obj>``
  422. .. versionchanged:: 1.0
  423. Now honors the remote working directory as manipulated by
  424. `~fabric.context_managers.cd`, and the local working directory as
  425. manipulated by `~fabric.context_managers.lcd`.
  426. .. versionchanged:: 1.0
  427. Now allows file-like objects in the ``local_path`` argument.
  428. .. versionchanged:: 1.0
  429. ``local_path`` may now contain interpolated path- and host-related
  430. variables.
  431. .. versionchanged:: 1.0
  432. Directories may be specified in the ``remote_path`` argument and will
  433. trigger recursive downloads.
  434. .. versionchanged:: 1.0
  435. Return value is now an iterable of downloaded local file paths, which
  436. also exhibits the ``.failed`` and ``.succeeded`` attributes.
  437. .. versionchanged:: 1.5
  438. Allow a ``name`` attribute on file-like objects for log output
  439. """
  440. # Handle empty local path / default kwarg value
  441. local_path = local_path or "%(host)s/%(path)s"
  442. # Test whether local_path is a path or a file-like object
  443. local_is_path = not (hasattr(local_path, 'write') \
  444. and callable(local_path.write))
  445. # Honor lcd() where it makes sense
  446. if local_is_path:
  447. local_path = apply_lcwd(local_path, env)
  448. ftp = SFTP(env.host_string)
  449. with closing(ftp) as ftp:
  450. home = ftp.normalize('.')
  451. # Expand home directory markers (tildes, etc)
  452. if remote_path.startswith('~'):
  453. remote_path = remote_path.replace('~', home, 1)
  454. if local_is_path:
  455. local_path = os.path.expanduser(local_path)
  456. # Honor cd() (assumes Unix style file paths on remote end)
  457. if not os.path.isabs(remote_path):
  458. # Honor cwd if it's set (usually by with cd():)
  459. if env.get('cwd'):
  460. remote_path_escaped = env.cwd.rstrip('/')
  461. remote_path_escaped = remote_path_escaped.replace('\\ ', ' ')
  462. remote_path = remote_path_escaped + '/' + remote_path
  463. # Otherwise, be relative to remote home directory (SFTP server's
  464. # '.')
  465. else:
  466. remote_path = posixpath.join(home, remote_path)
  467. # Track final local destination files so we can return a list
  468. local_files = []
  469. failed_remote_files = []
  470. try:
  471. # Glob remote path if necessary
  472. if '*' in remote_path or '?' in remote_path:
  473. names = ftp.glob(remote_path)
  474. # Handle "file not found" errors (like Paramiko does if we
  475. # explicitly try to grab a glob-like filename).
  476. if not names:
  477. raise IOError(errno.ENOENT, "No such file")
  478. else:
  479. names = [remote_path]
  480. # Handle invalid local-file-object situations
  481. if not local_is_path:
  482. if len(names) > 1 or ftp.isdir(names[0]):
  483. error("[%s] %s is a glob or directory, but local_path is a file object!" % (env.host_string, remote_path))
  484. for remote_path in names:
  485. if ftp.isdir(remote_path):
  486. result = ftp.get_dir(remote_path, local_path, use_sudo, temp_dir)
  487. local_files.extend(result)
  488. else:
  489. # Perform actual get. If getting to real local file path,
  490. # add result (will be true final path value) to
  491. # local_files. File-like objects are omitted.
  492. result = ftp.get(remote_path, local_path, use_sudo, local_is_path, os.path.basename(remote_path), temp_dir)
  493. if local_is_path:
  494. local_files.append(result)
  495. except Exception, e:
  496. failed_remote_files.append(remote_path)
  497. msg = "get() encountered an exception while downloading '%s'"
  498. error(message=msg % remote_path, exception=e)
  499. ret = _AttributeList(local_files if local_is_path else [])
  500. ret.failed = failed_remote_files
  501. ret.succeeded = not ret.failed
  502. return ret
  503. def _sudo_prefix_argument(argument, value):
  504. if value is None:
  505. return ""
  506. if str(value).isdigit():
  507. value = "#%s" % value
  508. return ' %s "%s"' % (argument, value)
  509. def _sudo_prefix(user, group=None):
  510. """
  511. Return ``env.sudo_prefix`` with ``user``/``group`` inserted if necessary.
  512. """
  513. # Insert env.sudo_prompt into env.sudo_prefix
  514. prefix = env.sudo_prefix % env
  515. if user is not None or group is not None:
  516. return "%s%s%s " % (prefix,
  517. _sudo_prefix_argument('-u', user),
  518. _sudo_prefix_argument('-g', group))
  519. return prefix
  520. def _shell_wrap(command, shell_escape, shell=True, sudo_prefix=None):
  521. """
  522. Conditionally wrap given command in env.shell (while honoring sudo.)
  523. """
  524. # Honor env.shell, while allowing the 'shell' kwarg to override it (at
  525. # least in terms of turning it off.)
  526. if shell and not env.use_shell:
  527. shell = False
  528. # Sudo plus space, or empty string
  529. if sudo_prefix is None:
  530. sudo_prefix = ""
  531. else:
  532. sudo_prefix += " "
  533. # If we're shell wrapping, prefix shell and space. Next, escape the command
  534. # if requested, and then quote it. Otherwise, empty string.
  535. if shell:
  536. shell = env.shell + " "
  537. if shell_escape:
  538. command = _shell_escape(command)
  539. command = '"%s"' % command
  540. else:
  541. shell = ""
  542. # Resulting string should now have correct formatting
  543. return sudo_prefix + shell + command
  544. def _prefix_commands(command, which):
  545. """
  546. Prefixes ``command`` with all prefixes found in ``env.command_prefixes``.
  547. ``env.command_prefixes`` is a list of strings which is modified by the
  548. `~fabric.context_managers.prefix` context manager.
  549. This function also handles a special-case prefix, ``cwd``, used by
  550. `~fabric.context_managers.cd`. The ``which`` kwarg should be a string,
  551. ``"local"`` or ``"remote"``, which will determine whether ``cwd`` or
  552. ``lcwd`` is used.
  553. """
  554. # Local prefix list (to hold env.command_prefixes + any special cases)
  555. prefixes = list(env.command_prefixes)
  556. # Handle current working directory, which gets its own special case due to
  557. # being a path string that gets grown/shrunk, instead of just a single
  558. # string or lack thereof.
  559. # Also place it at the front of the list, in case user is expecting another
  560. # prefixed command to be "in" the current working directory.
  561. cwd = env.cwd if which == 'remote' else env.lcwd
  562. redirect = " >/dev/null" if not win32 else ''
  563. if cwd:
  564. prefixes.insert(0, 'cd %s%s' % (cwd, redirect))
  565. glue = " && "
  566. prefix = (glue.join(prefixes) + glue) if prefixes else ""
  567. return prefix + command
  568. def _prefix_env_vars(command, local=False):
  569. """
  570. Prefixes ``command`` with any shell environment vars, e.g. ``PATH=foo ``.
  571. Currently, this only applies the PATH updating implemented in
  572. `~fabric.context_managers.path` and environment variables from
  573. `~fabric.context_managers.shell_env`.
  574. Will switch to using Windows style 'SET' commands when invoked by
  575. ``local()`` and on a Windows localhost.
  576. """
  577. env_vars = {}
  578. # path(): local shell env var update, appending/prepending/replacing $PATH
  579. path = env.path
  580. if path:
  581. if env.path_behavior == 'append':
  582. path = '$PATH:\"%s\"' % path
  583. elif env.path_behavior == 'prepend':
  584. path = '\"%s\":$PATH' % path
  585. elif env.path_behavior == 'replace':
  586. path = '\"%s\"' % path
  587. env_vars['PATH'] = path
  588. # shell_env()
  589. env_vars.update(env.shell_env)
  590. if env_vars:
  591. set_cmd, exp_cmd = '', ''
  592. if win32 and local:
  593. set_cmd = 'SET '
  594. else:
  595. exp_cmd = 'export '
  596. exports = ' '.join(
  597. '%s%s="%s"' % (set_cmd, k, v if k == 'PATH' else _shell_escape(v))
  598. for k, v in env_vars.iteritems()
  599. )
  600. shell_env_str = '%s%s && ' % (exp_cmd, exports)
  601. else:
  602. shell_env_str = ''
  603. return shell_env_str + command
  604. def _execute(channel, command, pty=True, combine_stderr=None,
  605. invoke_shell=False, stdout=None, stderr=None, timeout=None,
  606. capture_buffer_size=None):
  607. """
  608. Execute ``command`` over ``channel``.
  609. ``pty`` controls whether a pseudo-terminal is created.
  610. ``combine_stderr`` controls whether we call ``channel.set_combine_stderr``.
  611. By default, the global setting for this behavior (:ref:`env.combine_stderr
  612. <combine-stderr>`) is consulted, but you may specify ``True`` or ``False``
  613. here to override it.
  614. ``invoke_shell`` controls whether we use ``exec_command`` or
  615. ``invoke_shell`` (plus a handful of other things, such as always forcing a
  616. pty.)
  617. ``capture_buffer_size`` controls the length of the ring-buffers used to
  618. capture stdout/stderr. (This is ignored if ``invoke_shell=True``, since
  619. that completely disables capturing overall.)
  620. Returns a three-tuple of (``stdout``, ``stderr``, ``status``), where
  621. ``stdout``/``stderr`` are captured output strings and ``status`` is the
  622. program's return code, if applicable.
  623. """
  624. # stdout/stderr redirection
  625. stdout = stdout or sys.stdout
  626. stderr = stderr or sys.stderr
  627. # Timeout setting control
  628. timeout = env.command_timeout if (timeout is None) else timeout
  629. # What to do with CTRl-C?
  630. remote_interrupt = env.remote_interrupt
  631. with char_buffered(sys.stdin):
  632. # Combine stdout and stderr to get around oddball mixing issues
  633. if combine_stderr is None:
  634. combine_stderr = env.combine_stderr
  635. channel.set_combine_stderr(combine_stderr)
  636. # Assume pty use, and allow overriding of this either via kwarg or env
  637. # var. (invoke_shell always wants a pty no matter what.)
  638. using_pty = True
  639. if not invoke_shell and (not pty or not env.always_use_pty):
  640. using_pty = False
  641. # Request pty with size params (default to 80x24, obtain real
  642. # parameters if on POSIX platform)
  643. if using_pty:
  644. rows, cols = _pty_size()
  645. channel.get_pty(width=cols, height=rows)
  646. # Use SSH agent forwarding from 'ssh' if enabled by user
  647. config_agent = ssh_config().get('forwardagent', 'no').lower() == 'yes'
  648. forward = None
  649. if env.forward_agent or config_agent:
  650. forward = ssh.agent.AgentRequestHandler(channel)
  651. # Kick off remote command
  652. if invoke_shell:
  653. channel.invoke_shell()
  654. if command:
  655. channel.sendall(command + "\n")
  656. else:
  657. channel.exec_command(command=command)
  658. # Init stdout, stderr capturing. Must use lists instead of strings as
  659. # strings are immutable and we're using these as pass-by-reference
  660. stdout_buf = RingBuffer(value=[], maxlen=capture_buffer_size)
  661. stderr_buf = RingBuffer(value=[], maxlen=capture_buffer_size)
  662. if invoke_shell:
  663. stdout_buf = stderr_buf = None
  664. workers = (
  665. ThreadHandler('out', output_loop, channel, "recv",
  666. capture=stdout_buf, stream=stdout, timeout=timeout),
  667. ThreadHandler('err', output_loop, channel, "recv_stderr",
  668. capture=stderr_buf, stream=stderr, timeout=timeout),
  669. ThreadHandler('in', input_loop, channel, using_pty)
  670. )
  671. if remote_interrupt is None:
  672. remote_interrupt = invoke_shell
  673. if remote_interrupt and not using_pty:
  674. remote_interrupt = False
  675. while True:
  676. if channel.exit_status_ready():
  677. break
  678. else:
  679. # Check for thread exceptions here so we can raise ASAP
  680. # (without chance of getting blocked by, or hidden by an
  681. # exception within, recv_exit_status())
  682. for worker in workers:
  683. worker.raise_if_needed()
  684. try:
  685. time.sleep(ssh.io_sleep)
  686. except KeyboardInterrupt:
  687. if not remote_interrupt:
  688. raise
  689. channel.send('\x03')
  690. # Obtain exit code of remote program now that we're done.
  691. status = channel.recv_exit_status()
  692. # Wait for threads to exit so we aren't left with stale threads
  693. for worker in workers:
  694. worker.thread.join()
  695. worker.raise_if_needed()
  696. # Close channel
  697. channel.close()
  698. # Close any agent forward proxies
  699. if forward is not None:
  700. forward.close()
  701. # Update stdout/stderr with captured values if applicable
  702. if not invoke_shell:
  703. stdout_buf = ''.join(stdout_buf).strip()
  704. stderr_buf = ''.join(stderr_buf).strip()
  705. # Tie off "loose" output by printing a newline. Helps to ensure any
  706. # following print()s aren't on the same line as a trailing line prefix
  707. # or similar. However, don't add an extra newline if we've already
  708. # ended up with one, as that adds a entire blank line instead.
  709. if output.running \
  710. and (output.stdout and stdout_buf and not stdout_buf.endswith("\n")) \
  711. or (output.stderr and stderr_buf and not stderr_buf.endswith("\n")):
  712. print("")
  713. return stdout_buf, stderr_buf, status
  714. @needs_host
  715. def open_shell(command=None):
  716. """
  717. Invoke a fully interactive shell on the remote end.
  718. If ``command`` is given, it will be sent down the pipe before handing
  719. control over to the invoking user.
  720. This function is most useful for when you need to interact with a heavily
  721. shell-based command or series of commands, such as when debugging or when
  722. fully interactive recovery is required upon remote program failure.
  723. It should be considered an easy way to work an interactive shell session
  724. into the middle of a Fabric script and is *not* a drop-in replacement for
  725. `~fabric.operations.run`, which is also capable of interacting with the
  726. remote end (albeit only while its given command is executing) and has much
  727. stronger programmatic abilities such as error handling and stdout/stderr
  728. capture.
  729. Specifically, `~fabric.operations.open_shell` provides a better interactive
  730. experience than `~fabric.operations.run`, but use of a full remote shell
  731. prevents Fabric from determining whether programs run within the shell have
  732. failed, and pollutes the stdout/stderr stream with shell output such as
  733. login banners, prompts and echoed stdin.
  734. Thus, this function does not have a return value and will not trigger
  735. Fabric's failure handling if any remote programs result in errors.
  736. .. versionadded:: 1.0
  737. """
  738. _execute(channel=default_channel(), command=command, pty=True,
  739. combine_stderr=True, invoke_shell=True)
  740. @contextmanager
  741. def _noop():
  742. yield
  743. def _run_command(command, shell=True, pty=True, combine_stderr=True,
  744. sudo=False, user=None, quiet=False, warn_only=False, stdout=None,
  745. stderr=None, group=None, timeout=None, shell_escape=None,
  746. capture_buffer_size=None):
  747. """
  748. Underpinnings of `run` and `sudo`. See their docstrings for more info.
  749. """
  750. manager = _noop
  751. if warn_only:
  752. manager = warn_only_manager
  753. # Quiet's behavior is a superset of warn_only's, so it wins.
  754. if quiet:
  755. manager = quiet_manager
  756. with manager():
  757. # Set up new var so original argument can be displayed verbatim later.
  758. given_command = command
  759. # Check if shell_escape has been overridden in env
  760. if shell_escape is None:
  761. shell_escape = env.get('shell_escape', True)
  762. # Handle context manager modifications, and shell wrapping
  763. wrapped_command = _shell_wrap(
  764. _prefix_env_vars(_prefix_commands(command, 'remote')),
  765. shell_escape,
  766. shell,
  767. _sudo_prefix(user, group) if sudo else None
  768. )
  769. # Execute info line
  770. which = 'sudo' if sudo else 'run'
  771. if output.debug:
  772. print("[%s] %s: %s" % (env.host_string, which, wrapped_command))
  773. elif output.running:
  774. print("[%s] %s: %s" % (env.host_string, which, given_command))
  775. # Actual execution, stdin/stdout/stderr handling, and termination
  776. result_stdout, result_stderr, status = _execute(
  777. channel=default_channel(), command=wrapped_command, pty=pty,
  778. combine_stderr=combine_stderr, invoke_shell=False, stdout=stdout,
  779. stderr=stderr, timeout=timeout,
  780. capture_buffer_size=capture_buffer_size)
  781. # Assemble output string
  782. out = _AttributeString(result_stdout)
  783. err = _AttributeString(result_stderr)
  784. # Error handling
  785. out.failed = False
  786. out.command = given_command
  787. out.real_command = wrapped_command
  788. if status not in env.ok_ret_codes:
  789. out.failed = True
  790. msg = "%s() received nonzero return code %s while executing" % (
  791. which, status
  792. )
  793. if env.warn_only:
  794. msg += " '%s'!" % given_command
  795. else:
  796. msg += "!\n\nRequested: %s\nExecuted: %s" % (
  797. given_command, wrapped_command
  798. )
  799. error(message=msg, stdout=out, stderr=err)
  800. # Attach return code to output string so users who have set things to
  801. # warn only, can inspect the error code.
  802. out.return_code = status
  803. # Convenience mirror of .failed
  804. out.succeeded = not out.failed
  805. # Attach stderr for anyone interested in that.
  806. out.stderr = err
  807. return out
  808. @needs_host
  809. def run(command, shell=True, pty=True, combine_stderr=None, quiet=False,
  810. warn_only=False, stdout=None, stderr=None, timeout=None, shell_escape=None,
  811. capture_buffer_size=None):
  812. """
  813. Run a shell command on a remote host.
  814. If ``shell`` is True (the default), `run` will execute the given command
  815. string via a shell interpreter, the value of which may be controlled by
  816. setting ``env.shell`` (defaulting to something similar to ``/bin/bash -l -c
  817. "<command>"``.) Any double-quote (``"``) or dollar-sign (``$``) characters
  818. in ``command`` will be automatically escaped when ``shell`` is True (unless
  819. disabled by setting ``shell_escape=False``).
  820. When ``shell=False``, no shell wrapping or escaping will occur. (It's
  821. possible to specify ``shell=False, shell_escape=True`` if desired, which
  822. will still trigger escaping of dollar signs, etc but will not wrap with a
  823. shell program invocation).
  824. `run` will return the result of the remote program's stdout as a single
  825. (likely multiline) string. This string will exhibit ``failed`` and
  826. ``succeeded`` boolean attributes specifying whether the command failed or
  827. succeeded, and will also include the return code as the ``return_code``
  828. attribute. Furthermore, it includes a copy of the requested & actual
  829. command strings executed, as ``.command`` and ``.real_command``,
  830. respectively.
  831. To lessen memory use when running extremely verbose programs (and,
  832. naturally, when having access to their full output afterwards is not
  833. necessary!) you may limit how much of the program's stdout/err is stored by
  834. setting ``capture_buffer_size`` to an integer value.
  835. .. warning::
  836. Do not set ``capture_buffer_size`` to any value smaller than the length
  837. of ``env.sudo_prompt`` or you will likely break the functionality of
  838. `sudo`! Ditto any user prompts stored in ``env.prompts``.
  839. .. note::
  840. This value is used for each buffer independently, so e.g. ``1024`` may
  841. result in storing a total of ``2048`` bytes if there's data in both
  842. streams.)
  843. Any text entered in your local terminal will be forwarded to the remote
  844. program as it runs, thus allowing you to interact with password or other
  845. prompts naturally. For more on how this works, see
  846. :doc:`/usage/interactivity`.
  847. You may pass ``pty=False`` to forego creation of a pseudo-terminal on the
  848. remote end in case the presence of one causes problems for the command in
  849. question. However, this will force Fabric itself to echo any and all input
  850. you type while the command is running, including sensitive passwords. (With
  851. ``pty=True``, the remote pseudo-terminal will echo for you, and will
  852. intelligently handle password-style prompts.) See :ref:`pseudottys` for
  853. details.
  854. Similarly, if you need to programmatically examine the stderr stream of the
  855. remote program (exhibited as the ``stderr`` attribute on this function's
  856. return value), you may set ``combine_stderr=False``. Doing so has a high
  857. chance of causing garbled output to appear on your terminal (though the
  858. resulting strings returned by `~fabric.operations.run` will be properly
  859. separated). For more info, please read :ref:`combine_streams`.
  860. To ignore non-zero return codes, specify ``warn_only=True``. To both ignore
  861. non-zero return codes *and* force a command to run silently, specify
  862. ``quiet=True``.
  863. To override which local streams are used to display remote stdout and/or
  864. stderr, specify ``stdout`` or ``stderr``. (By default, the regular
  865. ``sys.stdout`` and ``sys.stderr`` Python stream objects are used.)
  866. For example, ``run("command", stderr=sys.stdout)`` would print the remote
  867. standard error to the local standard out, while preserving it as its own
  868. distinct attribute on the return value (as per above.) Alternately, you
  869. could even provide your own stream objects or loggers, e.g. ``myout =
  870. StringIO(); run("command", stdout=myout)``.
  871. If you want an exception raised when the remote program takes too long to
  872. run, specify ``timeout=N`` where ``N`` is an integer number of seconds,
  873. after which to time out. This will cause ``run`` to raise a
  874. `~fabric.exceptions.CommandTimeout` exception.
  875. If you want to disable Fabric's automatic attempts at escaping quotes,
  876. dollar signs etc., specify ``shell_escape=False``.
  877. Examples::
  878. run("ls /var/www/")
  879. run("ls /home/myuser", shell=False)
  880. output = run('ls /var/www/site1')
  881. run("take_a_long_time", timeout=5)
  882. .. versionadded:: 1.0
  883. The ``succeeded`` and ``stderr`` return value attributes, the
  884. ``combine_stderr`` kwarg, and interactive behavior.
  885. .. versionchanged:: 1.0
  886. The default value of ``pty`` is now ``True``.
  887. .. versionchanged:: 1.0.2
  888. The default value of ``combine_stderr`` is now ``None`` instead of
  889. ``True``. However, the default *behavior* is unchanged, as the global
  890. setting is still ``True``.
  891. .. versionadded:: 1.5
  892. The ``quiet``, ``warn_only``, ``stdout`` and ``stderr`` kwargs.
  893. .. versionadded:: 1.5
  894. The return value attributes ``.command`` and ``.real_command``.
  895. .. versionadded:: 1.6
  896. The ``timeout`` argument.
  897. .. versionadded:: 1.7
  898. The ``shell_escape`` argument.
  899. .. versionadded:: 1.11
  900. The ``capture_buffer_size`` argument.
  901. """
  902. return _run_command(
  903. command, shell, pty, combine_stderr, quiet=quiet,
  904. warn_only=warn_only, stdout=stdout, stderr=stderr, timeout=timeout,
  905. shell_escape=shell_escape, capture_buffer_size=capture_buffer_size,
  906. )
  907. @needs_host
  908. def sudo(command, shell=True, pty=True, combine_stderr=None, user=None,
  909. quiet=False, warn_only=False, stdout=None, stderr=None, group=None,
  910. timeout=None, shell_escape=None, capture_buffer_size=None):
  911. """
  912. Run a shell command on a remote host, with superuser privileges.
  913. `sudo` is identical in every way to `run`, except that it will always wrap
  914. the given ``command`` in a call to the ``sudo`` program to provide
  915. superuser privileges.
  916. `sudo` accepts additional ``user`` and ``group`` arguments, which are
  917. passed to ``sudo`` and allow you to run as some user and/or group other
  918. than root. On most systems, the ``sudo`` program can take a string
  919. username/group or an integer userid/groupid (uid/gid); ``user`` and
  920. ``group`` may likewise be strings or integers.
  921. You may set :ref:`env.sudo_user <sudo_user>` at module level or via
  922. `~fabric.context_managers.settings` if you want multiple ``sudo`` calls to
  923. have the same ``user`` value. An explicit ``user`` argument will, of
  924. course, override this global setting.
  925. Examples::
  926. sudo("~/install_script.py")
  927. sudo("mkdir /var/www/new_docroot", user="www-data")
  928. sudo("ls /home/jdoe", user=1001)
  929. result = sudo("ls /tmp/")
  930. with settings(sudo_user='mysql'):
  931. sudo("whoami") # prints 'mysql'
  932. .. versionchanged:: 1.0
  933. See the changed and added notes for `~fabric.operations.run`.
  934. .. versionchanged:: 1.5
  935. Now honors :ref:`env.sudo_user <sudo_user>`.
  936. .. versionadded:: 1.5
  937. The ``quiet``, ``warn_only``, ``stdout`` and ``stderr`` kwargs.
  938. .. versionadded:: 1.5
  939. The return value attributes ``.command`` and ``.real_command``.
  940. .. versionadded:: 1.7
  941. The ``shell_escape`` argument.
  942. .. versionadded:: 1.11
  943. The ``capture_buffer_size`` argument.
  944. """
  945. return _run_command(
  946. command, shell, pty, combine_stderr, sudo=True,
  947. user=user if user else env.sudo_user,
  948. group=group, quiet=quiet, warn_only=warn_only, stdout=stdout,
  949. stderr=stderr, timeout=timeout, shell_escape=shell_escape,
  950. capture_buffer_size=capture_buffer_size,
  951. )
  952. def local(command, capture=False, shell=None):
  953. """
  954. Run a command on the local system.
  955. `local` is simply a convenience wrapper around the use of the builtin
  956. Python ``subprocess`` module with ``shell=True`` activated. If you need to
  957. do anything special, consider using the ``subprocess`` module directly.
  958. ``shell`` is passed directly to `subprocess.Popen
  959. <http://docs.python.org/library/subprocess.html#subprocess.Popen>`_'s
  960. ``execute`` argument (which determines the local shell to use.) As per the
  961. linked documentation, on Unix the default behavior is to use ``/bin/sh``,
  962. so this option is useful for setting that value to e.g. ``/bin/bash``.
  963. `local` is not currently capable of simultaneously printing and
  964. capturing output, as `~fabric.operations.run`/`~fabric.operations.sudo`
  965. do. The ``capture`` kwarg allows you to switch between printing and
  966. capturing as necessary, and defaults to ``False``.
  967. When ``capture=False``, the local subprocess' stdout and stderr streams are
  968. hooked up directly to your terminal, though you may use the global
  969. :doc:`output controls </usage/output_controls>` ``output.stdout`` and
  970. ``output.stderr`` to hide one or both if desired. In this mode, the return
  971. value's stdout/stderr values are always empty.
  972. When ``capture=True``, you will not see any output from the subprocess in
  973. your terminal, but the return value will contain the captured
  974. stdout/stderr.
  975. In either case, as with `~fabric.operations.run` and
  976. `~fabric.operations.sudo`, this return value exhibits the ``return_code``,
  977. ``stderr``, ``failed``, ``succeeded``, ``command`` and ``real_command``
  978. attributes. See `run` for details.
  979. `~fabric.operations.local` will honor the `~fabric.context_managers.lcd`
  980. context manager, allowing you to control its current working directory
  981. independently of the remote end (which honors
  982. `~fabric.context_managers.cd`).
  983. .. versionchanged:: 1.0
  984. Added the ``succeeded`` and ``stderr`` attributes.
  985. .. versionchanged:: 1.0
  986. Now honors the `~fabric.context_managers.lcd` context manager.
  987. .. versionchanged:: 1.0
  988. Changed the default value of ``capture`` from ``True`` to ``False``.
  989. .. versionadded:: 1.9
  990. The return value attributes ``.command`` and ``.real_command``.
  991. """
  992. given_command = command
  993. # Apply cd(), path() etc
  994. with_env = _prefix_env_vars(command, local=True)
  995. wrapped_command = _prefix_commands(with_env, 'local')
  996. if output.debug:
  997. print("[localhost] local: %s" % (wrapped_command))
  998. elif output.running:
  999. print("[localhost] local: " + given_command)
  1000. # Tie in to global output controls as best we can; our capture argument
  1001. # takes precedence over the output settings.
  1002. dev_null = None
  1003. if capture:
  1004. out_stream = subprocess.PIPE
  1005. err_stream = subprocess.PIPE
  1006. else:
  1007. dev_null = open(os.devnull, 'w+')
  1008. # Non-captured, hidden streams are discarded.
  1009. out_stream = None if output.stdout else dev_null
  1010. err_stream = None if output.stderr else dev_null
  1011. try:
  1012. cmd_arg = wrapped_command if win32 else [wrapped_command]
  1013. p = subprocess.Popen(cmd_arg, shell=True, stdout=out_stream,
  1014. stderr=err_stream, executable=shell,
  1015. close_fds=(not win32))
  1016. (stdout, stderr) = p.communicate()
  1017. finally:
  1018. if dev_null is not None:
  1019. dev_null.close()
  1020. # Handle error condition (deal with stdout being None, too)
  1021. out = _AttributeString(stdout.strip() if stdout else "")
  1022. err = _AttributeString(stderr.strip() if stderr else "")
  1023. out.command = given_command
  1024. out.real_command = wrapped_command
  1025. out.failed = False
  1026. out.return_code = p.returncode
  1027. out.stderr = err
  1028. if p.returncode not in env.ok_ret_codes:
  1029. out.failed = True
  1030. msg = "local() encountered an error (return code %s) while executing '%s'" % (p.returncode, command)
  1031. error(message=msg, stdout=out, stderr=err)
  1032. out.succeeded = not out.failed
  1033. # If we were capturing, this will be a string; otherwise it will be None.
  1034. return out
  1035. @needs_host
  1036. def reboot(wait=120, command='reboot', use_sudo=True):
  1037. """
  1038. Reboot the remote system.
  1039. Will temporarily tweak Fabric's reconnection settings (:ref:`timeout` and
  1040. :ref:`connection-attempts`) to ensure that reconnection does not give up
  1041. for at least ``wait`` seconds.
  1042. .. note::
  1043. As of Fabric 1.4, the ability to reconnect partway through a session no
  1044. longer requires use of internal APIs. While we are not officially
  1045. deprecating this function, adding more features to it will not be a
  1046. priority.
  1047. Users who want greater control
  1048. are encouraged to check out this function's (6 lines long, well
  1049. commented) source code and write their own adaptation using different
  1050. timeout/attempt values or additional logic.
  1051. .. versionadded:: 0.9.2
  1052. .. versionchanged:: 1.4
  1053. Changed the ``wait`` kwarg to be optional, and refactored to leverage
  1054. the new reconnection functionality; it may not actually have to wait
  1055. for ``wait`` seconds before reconnecting.
  1056. .. versionchanged:: 1.11
  1057. Added ``use_sudo`` as a kwarg. Maintained old functionality by setting
  1058. the default value to True.
  1059. """
  1060. # Shorter timeout for a more granular cycle than the default.
  1061. timeout = 5
  1062. # Use 'wait' as max total wait time
  1063. attempts = int(round(float(wait) / float(timeout)))
  1064. # Don't bleed settings, since this is supposed to be self-contained.
  1065. # User adaptations will probably want to drop the "with settings()" and
  1066. # just have globally set timeout/attempts values.
  1067. with settings(
  1068. hide('running'),
  1069. timeout=timeout,
  1070. connection_attempts=attempts
  1071. ):
  1072. (sudo if use_sudo else run)(command)
  1073. # Try to make sure we don't slip in before pre-reboot lockdown
  1074. time.sleep(5)
  1075. # This is actually an internal-ish API call, but users can simply drop
  1076. # it in real fabfile use -- the next run/sudo/put/get/etc call will
  1077. # automatically trigger a reconnect.
  1078. # We use it here to force the reconnect while this function is still in
  1079. # control and has the above timeout settings enabled.
  1080. connections.connect(env.host_string)
  1081. # At this point we should be reconnected to the newly rebooted server.