def AutoDetection(self): msg = '' # Trying to call fastjet-config with which result = ShellCommand.Which('fastjet-config', mute=True) if len(result) == 0: msg = 'The FastJet package is not found.' return DetectStatusType.UNFOUND, msg islink = os.path.islink(result[0]) if not islink: self.bin_file = os.path.normpath(result[0]) else: self.bin_file = os.path.normpath(os.path.realpath(result[0])) self.bin_path = os.path.dirname(self.bin_file) # Debug mode if self.debug: self.logger.debug(" which: " + str(result[0]) + " [is it a link? " + str(islink) + "]") if islink: self.logger.debug(" -> " + os.path.realpath(result[0])) # Which all if self.debug: result = ShellCommand.Which('fastjet-config', all=True, mute=True) if len(result) == 0: msg = 'The FastJet package is not found.' return DetectStatusType.UNFOUND, msg self.logger.debug(" which-all: ") for file in result: self.logger.debug(" - " + str(file)) return DetectStatusType.FOUND, msg
def ExtractInfo(self): # Which all if self.debug: result = ShellCommand.Which('make',all=True,mute=True) if len(result)==0: self.logger.error('GNU Make not found. Please install it before ' + \ 'using MadAnalysis 5') return False self.logger.debug(" which-all: ") for file in result: self.logger.debug(" - "+str(file)) # Getting the version ok, out, err = ShellCommand.ExecuteWithCapture(['make','--version'],'./') if not ok: self.logger.error('GNU Make not found. Please install it before ' + \ 'using MadAnalysis 5') return False lines=out.split('\n') if len(lines)==0: self.logger.error('command "make --version" seems to not give the GNU Make version') return False firstline=lines[0] firstline=firstline.lstrip() firstline=firstline.rstrip() self.version = str(firstline) if self.debug: self.logger.debug(" version: " + self.version) # Ok return True
def events(): ll = [] def handler(item): ll.append(item) cmd = ShellCommand('tail', '/var/log/syslog') yield 'event: ping\n' yield 'data: Executing "{}"\n\n'.format(cmd) asyncio.set_event_loop(LOOP) future = asyncio.ensure_future(cmd.run(handler), loop=LOOP) while LOOP.run_until_complete(future): while ll: yield 'event: ping\n' yield 'data: {}\n\n'.format(ll.pop(0)) else: if future.done(): break asyncio.sleep(.1) yield 'event: close\n' yield 'data: Done! Command {cmd}. Exit Code {exit_code}\n\n'.format( cmd=cmd, exit_code=future.result().exit_code )
def ExtractInfo(self): theCommands = [self.bin_path + '/fastjet-config', '--version'] ok, out, err = ShellCommand.ExecuteWithCapture(theCommands, './') if not ok: msg = 'fastjet-config program does not work properly.' return False, msg out = out.lstrip() out = out.rstrip() self.version = str(out) if self.debug: self.logger.debug(" version: " + self.version) # Using fastjet-config for getting lib and header paths self.logger.debug("Trying to get library and header paths ...") theCommands = [ self.bin_path + '/fastjet-config', '--libs', '--plugins' ] ok, out, err = ShellCommand.ExecuteWithCapture(theCommands, './') if not ok: msg = 'fastjet-config program does not work properly.' return False, msg # Extracting FastJet library and header path out = out.lstrip() out = out.rstrip() self.logger.debug(" Lib flags: " + str(out)) words = out.split() for word in words: if word.startswith('-L') and not word[2:] in self.lib_paths: self.lib_paths.append(word[2:]) if self.debug: self.logger.debug(" Lib path: " + str(self.lib_paths)) # Ok return True
def RunJob(self, dataset): # Getting the dataset name name = InstanceName.Get(dataset.name) # Creating Output folder is not defined if not os.path.isdir(self.path + "/Output/" + name): os.mkdir(self.path + "/Output/" + name) # folder where the program is launched folder = self.path + '/Build/' # shell command commands = ['./MadAnalysis5job'] # Weighted events if not dataset.weighted_events: commands.append('--no_event_weight') # Release commands.append('--ma5_version="'+\ self.main.archi_info.ma5_version+';'+\ self.main.archi_info.ma5_date+'"') # Inputs commands.append('../Input/' + name + '.list') # Running SampleAnalyzer if self.main.redirectSAlogger: result = ShellCommand.ExecuteWithMA5Logging(commands, folder) else: result = ShellCommand.Execute(commands, folder) return result
def ExtractInfo(self): # Debug general if self.debug: self.logger.debug("") self.logger.debug(" Python release: " + str(platform.python_version())) self.logger.debug(" Python build: " + str(platform.python_build())) self.logger.debug(" Python compiler: " + str(platform.python_compiler())) self.logger.debug(" Python prefix: " + str(sys.prefix)) self.logger.debug(" Python executable used: " + str(sys.executable)) # Which python if self.debug: self.logger.debug(" sys.executable: " + str(sys.executable)) result = ShellCommand.Which('python', all=False, mute=True) if len(result) == 0: self.logger.error('python compiler not found. Please install it before ' + \ 'using MadAnalysis 5') return False self.logger.debug(" which: " + str(result[0])) # Which all if self.debug: result = ShellCommand.Which('python', all=True, mute=True) if len(result) == 0: self.logger.error('g++ compiler not found. Please install it before ' + \ 'using MadAnalysis 5') return False self.logger.debug(" which-all: ") for file in result: self.logger.debug(" - " + str(file)) # Python paths if self.debug: self.logger.debug(" Python internal paths: ") tmp = sys.path for path in tmp: self.logger.debug(" - " + path) self.logger.debug(" $PYTHONPATH: ") try: tmp = os.environ['PYTHONPATH'] except: tmp = [] if len(tmp) == 0: self.logger.debug(" EMPTY OR NOT FOUND") else: tmp = tmp.split(':') for path in tmp: self.logger.debug(" - " + path) self.logger.debug("") # Ok return True
def setUp(self): """Set up for test.""" # Make sure the input and output options are explicitly set to # [] otherwise they hang around from previous tests. self.command = ShellCommand(input_options=[], output_options=[]) self.expected_executable = "" self.expected_base_options = [] self.expected_input_options = [] self.expected_filter_options = [] self.expected_output_options = []
def link(self, builder): if len(self.objects) == 0: return False compiler = builder.toolchain.compiler target = builder.output_file(self) flags = map(lambda x: x.path, self.objects) + self.ldflags + ['-o', target] cmd = ShellCommand(compiler, flags) builder.print_msg('LD', target) code, output = cmd.run(verbose=builder.verbose) print output.strip() return code == 0
def test_command_string(self): """Test that command string matches expected.""" args = (self.expected_base_options + self.expected_input_options + self.expected_filter_options + self.expected_output_options) expected_cmd_unquoted = ("{exe} {arg}".format( exe=self.expected_executable, arg=" ".join(args))) expected_cmd_quoted = ('{exe} {arg}'.format( exe=ShellCommand.shellquote(self.expected_executable), arg=" ".join([ShellCommand.shellquote(a) for a in args]))) with self.subTest(msg="unquoted command string matches"): self.assertEqual(self.command.command_string(quote=False), expected_cmd_unquoted) with self.subTest(msg="quoted command string matches"): self.assertEqual(self.command.command_string(quote=True), expected_cmd_quoted)
def Configure(self): # Updating the makefile TheCommand = [ 'mv', self.installdir + '/Build/Makefile', self.installdir + '/Build/Makefile.save' ] ok = ShellCommand.Execute(TheCommand, self.main.archi_info.ma5dir) if not ok: return False inp = open(self.installdir + '/Build/Makefile.save', 'r') out = open(self.installdir + '/Build/Makefile', 'w') for line in inp: out.write(line) if 'LIBFLAGS += -lcommons_for_ma5' in line: out.write("LIBFLAGS += -lMinuit\n") inp.close() out.close() TheCommand = ['rm', '-f', self.installdir + '/Build/Makefile.save'] ok = ShellCommand.Execute(TheCommand, self.main.archi_info.ma5dir) if not ok: return False # Updating the main in order to get a correct file name for the template analysis TheCommand = [ 'mv', self.installdir + '/Build/Main/main.cpp', self.installdir + '/Build/Main/main.cpp.save' ] ok = ShellCommand.Execute(TheCommand, self.main.archi_info.ma5dir) if not ok: return False inp = open(self.installdir + '/Build/Main/main.cpp.save', 'r') out = open(self.installdir + '/Build/Main/main.cpp', 'w') for line in inp: if 'user.saf' in line: out.write( " manager.InitializeAnalyzer(\"cms_sus_13_011\",\"cms_sus_13_011.saf\",parametersA1);\n" ) else: out.write(line) inp.close() out.close() TheCommand = [ 'rm', '-f', self.installdir + '/Build/Main/main.cpp.save' ] ok = ShellCommand.Execute(TheCommand, self.main.archi_info.ma5dir) if not ok: return False return ok
def compile_object(self, builder, source, flags=None): compiler = builder.toolchain.compiler obj = os.path.join(builder.tmpdir, source.objectfile) if source.is_newer(obj) is False: return {'source': source, 'status': 'skipped'} flags = [] if flags is None else flags include = self._gen_include_flags() flags = [source.path, '-c'] + include + self.cflags + flags + ['-o', obj] cmd = ShellCommand(compiler, flags) code, output = cmd.run(verbose=builder.verbose) if 0 == code: status = 'success' self.compiled_objects += [obj] else: status = 'failed' return {'source': source, 'status': status, 'output': output}
def untar(logname, downloaddir, installdir, tarball): # Unpacking the folder theCommands = ['tar', 'xzf', tarball, '-C', installdir] logging.getLogger('MA5').debug('shell command: ' + ' '.join(theCommands)) logging.getLogger('MA5').debug('exected dir: ' + downloaddir) ok, out= ShellCommand.ExecuteWithLog(theCommands,\ logname,\ downloaddir,\ silent=False) if not ok: return False, '' # # Removing the tarball # toRemove=installdir+'/'+tarball # logging.getLogger('MA5').debug('removing the file: '+toRemove) # try: # os.remove(toRemove) # except: # logging.getLogger('MA5').debug('impossible to remove the tarball: '+tarball) # Getting the good folder import glob folder_content = glob.glob(installdir + '/*') logging.getLogger('MA5').debug('content of ' + installdir + ': ' + str(folder_content)) if len(folder_content) == 0: logging.getLogger('MA5').error( 'The content of the tarball is empty') return False, '' elif len(folder_content) == 1: return True, folder_content[0] else: return True, installdir
def test_shellquote(self): """Test shell quoting (static method).""" test_data = ( (None, None, "None ⇒ None"), ("", "", "(empty string) ⇒ (empty string)"), (" ", '" "', '␢ ⇒ " "'), (" ", '" "', '␢␢␢␢␢ ⇒ " "'), ("foobar", "foobar", "foobar ⇒ foobar"), ("foo bar", '"foo bar"', 'foo bar ⇒ "foo bar"'), ('"foobar"', '\'"foobar"\'', '"foobar" ⇒ \'"foobar"\''), ("'foobar'", "'foobar'", "'foobar' ⇒ 'foobar'"), ("foo 'bar'", '"foo \'bar\'"', "foo 'bar' ⇒ \"foo 'bar'\""), ('foo"bar', '\'foo"bar\'', 'foo"bar ⇒ \'foo"bar\''), ("foo.bar", '"foo.bar"', 'foo.bar ⇒ "foo.bar"'), ("foo(bar)", '"foo(bar)"', 'foo(bar) ⇒ "foo(bar)"'), ("[foobar]", '"[foobar]"', '[foobar] ⇒ "[foobar]"'), ("foo[bar", '"foo[bar"', 'foo[bar ⇒ "foo[bar"'), ("/foo/bar", "/foo/bar", "/foo/bar ⇒ /foo/bar"), ("-f", "-f", "-f ⇒ -f"), ("--foobar", "--foobar", "--foobar ⇒ --foobar"), ("(", r"\(", r"( ⇒ \("), (")", r"\)", r"( ⇒ \)"), ("'", '"\'"', '\' ⇒ "\'"'), ) for original, expected, description in test_data: with self.subTest(msg=description): self.assertEqual(ShellCommand.shellquote(original), expected)
def MrProper(self,package,folder): # log file name if package in ['process','commons','configuration']: logfile = folder+'/mrproper.log' elif package in ['test_process','test_commons','test_zlib','test_root','test_fastjet','test_delphes','test_delphesMA5tune']: logfile = folder+'/mrproper_'+package[5:]+'.log' else: logfile = folder+'/mrproper_'+package+'.log' self.logger.debug("LogFile: "+logfile) # makefile if package in ['process','commons','test','configuration']: makefile = 'Makefile' elif package in ['test_process','test_commons','test_zlib','test_root','test_fastjet','test_delphes','test_delphesMA5tune']: makefile = 'Makefile_'+package[5:] else: makefile = 'Makefile_'+package self.logger.debug("Makefile: "+makefile) # shell command commands = ['make','mrproper','--file='+makefile] self.logger.debug("Command: "+" ".join(commands)) # call result, out = ShellCommand.ExecuteWithLog(commands,logfile,folder) # return result if not result: self.logger.error('impossible to clean the project. For more details, see the log file:') self.logger.error(logfile) return result
def Clean(self,package,folder): # log file name if package in ['process','commons','configuration','test']: logfile = folder+'/cleanup.log' elif package in ['test_process','test_commons','test_zlib','test_fastjet','test_root','test_delphes','test_delphesMA5tune']: logfile = folder+'/cleanup_'+package[5:]+'.log' else: logfile = folder+'/cleanup_'+package+'.log' # makefile if package in ['process','commons','test','configuration']: makefile = 'Makefile' elif package in ['test_process','test_commons','test_zlib','test_fastjet','test_root','test_delphes','test_delphesMA5tune']: makefile = 'Makefile_'+package[5:] else: makefile = 'Makefile_'+package # shell command commands = ['make','clean','--file='+makefile] # call result, out = ShellCommand.ExecuteWithLog(commands,logfile,folder) # return result if not result: self.logger.error('impossible to clean the project. For more details, see the log file:') self.logger.error(logfile) return result
def test_executable_string(self): """Test that executable path matches expected.""" with self.subTest(msg="unquoted paths match"): self.assertEqual(self.command.executable_string(quote=False), self.expected_executable) with self.subTest(msg="unquoted paths match"): # Note: don't explicitly specify quoted value, because # the executable path will vary across different systems. self.assertEqual(self.command.executable_string(quote=True), ShellCommand.shellquote(self.expected_executable))
def AutoDetection(self): # Which result = ShellCommand.Which('latex', all=False, mute=True) if len(result) == 0: return DetectStatusType.UNFOUND, '' if self.debug: self.logger.debug(" which: " + str(result[0])) # Ok return DetectStatusType.FOUND, ''
def AutoDetection(self): msg = '' # Trying to call root-config with which result = ShellCommand.Which('root-config') if len(result) == 0: msg = 'ROOT module called "root-config" is not detected.\n'\ +'Two explanations :n'\ +' - ROOT is not installed. You can download it '\ +'from http://root.cern.ch\n'\ +' - ROOT binary folder must be placed in the '\ +'global environment variable $PATH' return DetectStatusType.UNFOUND, msg islink = os.path.islink(result[0]) if not islink: self.bin_file = os.path.normpath(result[0]) else: self.bin_file = os.path.normpath(os.path.realpath(result[0])) self.bin_path = os.path.dirname(self.bin_file) # Debug mode if self.debug: self.logger.debug(" which: " + str(result[0]) + " [is it a link? " + str(islink) + "]") if islink: self.logger.debug(" -> " + os.path.realpath(result[0])) # Which all if self.debug: result = ShellCommand.Which('root-config', all=True, mute=True) if len(result) == 0: msg = 'ROOT module called "root-config" is not detected.\n'\ +'Two explanations :n'\ +' - ROOT is not installed. You can download it '\ +'from http://root.cern.ch\n'\ +' - ROOT binary folder must be placed in the '\ +'global environment variable $PATH' DetectStatusType.ISSUE, msg self.logger.debug(" which-all: ") for file in result: self.logger.debug(" - " + str(file)) return DetectStatusType.FOUND, msg
def test_argument_string(self): """Test that argument string matches expected.""" args = (self.expected_base_options + self.expected_input_options + self.expected_filter_options + self.expected_output_options) with self.subTest(msg="unquoted agruments match"): self.assertEqual(self.command.argument_string(quote=False), " ".join(args)) with self.subTest(msg="quoted agruments match"): self.assertEqual( self.command.argument_string(quote=True), " ".join([ShellCommand.shellquote(a) for a in args]))
def Build(self): # Input theCommands=['make','-j'+str(self.ncores)] logname=os.path.normpath(self.installdir+'/Build/compilation.log') # Execute logging.getLogger('MA5').debug('shell command: '+' '.join(theCommands)) ok, out= ShellCommand.ExecuteWithLog(theCommands,logname,self.installdir+'/Build',silent=False) # return result if not ok: logging.getLogger('MA5').error('impossible to build the project. For more details, see the log file:') logging.getLogger('MA5').error(logname) return ok
def ExtractInfo(self): # Which all if self.debug: result = ShellCommand.Which('latex', all=True, mute=True) if len(result) == 0: return False self.logger.debug(" which-all: ") for file in result: self.logger.debug(" - " + str(file)) # Ok return True
def AutoDetection(self): msg = '' # Which result = ShellCommand.Which('make',all=False,mute=True) if len(result)==0: msg = "GNU Make not found. Please install it before using MadAnalysis 5" return DetectStatusType.UNFOUND, msg if self.debug: self.logger.debug(" which: " + str(result[0])) # Ok return DetectStatusType.FOUND, msg
def Remove(self,question=True): import time bkpname = "pad_forma5tune-v" + time.strftime("%Y%m%d-%Hh%M") + ".tgz" logging.getLogger('MA5').info(" => Backuping the previous installation: " + bkpname) logname = os.path.normpath(self.main.archi_info.ma5dir+'/pad-backup.log') TheCommand = ['tar', 'czf', bkpname, 'PADForMA5tune'] logging.getLogger('MA5').debug('Shell command: '+' '.join(TheCommand)) ok, out= ShellCommand.ExecuteWithLog(TheCommand,logname,self.main.archi_info.ma5dir,silent=False) if not ok: return False logging.getLogger('MA5').info(" => Backup done") from madanalysis.IOinterface.folder_writer import FolderWriter return FolderWriter.RemoveDirectory(self.installdir,question)
def Configure(self): # Input theCommands=['./configure','--prefix='+self.installdir] logname=os.path.normpath(self.installdir+'/configuration.log') # Execute logging.getLogger('MA5').debug('shell command: '+' '.join(theCommands)) ok, out= ShellCommand.ExecuteWithLog(theCommands,\ logname,\ self.tmpdir,\ silent=False) # return result if not ok: logging.getLogger('MA5').error('impossible to configure the project. For more details, see the log file:') logging.getLogger('MA5').error(logname) return ok
def Install(self): # Input theCommands=['make','install'] logname=os.path.normpath(self.installdir+'/installation_contrib.log') # Execute logging.getLogger('MA5').debug('shell command: '+' '.join(theCommands)) ok, out= ShellCommand.ExecuteWithLog(theCommands,\ logname,\ self.tmpdir,\ silent=False) # return result if not ok: logging.getLogger('MA5').error('impossible to build the project. For more details, see the log file:') logging.getLogger('MA5').error(logname) return ok
def Clean(self): # Input theCommands = ['make', 'clean'] logname = os.path.normpath(self.installdir + '/clean.log') # Execute self.logger.debug('shell command: ' + ' '.join(theCommands)) ok, out= ShellCommand.ExecuteWithLog(theCommands,\ logname,\ self.installdir,\ silent=False) # return result if not ok: self.logger.error( 'impossible to clean the project. For more details, see the log file:' ) self.logger.error(logname) return ok
def Compile(self, ncores, package, folder): # number of cores strcores = '' if ncores > 1: strcores = '-j' + str(ncores) # log file name if package in ['process', 'commons', 'test', 'configuration']: logfile = folder + '/compilation.log' elif package in [ 'test_process', 'test_commons', 'test_zlib', 'test_fastjet', 'test_root', 'test_delphes', 'test_delphesMA5tune' ]: logfile = folder + '/compilation_' + package[5:] + '.log' else: logfile = folder + '/compilation_' + package + '.log' # makefile if package in ['process', 'commons', 'test', 'configuration']: makefile = 'Makefile' elif package in [ 'test_process', 'test_commons', 'test_zlib', 'test_fastjet', 'test_root', 'test_delphes', 'test_delphesMA5tune' ]: makefile = 'Makefile_' + package[5:] else: makefile = 'Makefile_' + package # shell command if strcores == '': commands = ['make', 'compile', '--file=' + makefile] else: commands = ['make', 'compile', strcores, '--file=' + makefile] # call result, out = ShellCommand.ExecuteWithLog(commands, logfile, folder) # return result if not result: self.logger.error( 'impossible to compile the project. For more details, see the log file:' ) self.logger.error(logfile) return result
def MakePAD(self, PADdir, dirname, main, silent=False): if not silent: self.logger.info(' Compiling the PAD in ' + PADdir) compiler = LibraryWriter('lib', main) ncores = compiler.get_ncores2() if ncores > 1: strcores = '-j' + str(ncores) command = ['make', strcores] logfile = PADdir + '/Build/PADcompilation.log' result, out = ShellCommand.ExecuteWithLog(command, logfile, PADdir + '/Build') if not result: self.logger.error('Impossible to compile the PAD....'+\ ' For more details, see the log file:') self.logger.error(logfile) return False return True
def make_pad(self): # Initializing the compiler logging.getLogger('MA5').info(' Compiling the PAD located in ' +self.pad) compiler = LibraryWriter('lib',self.main) ncores = compiler.get_ncores2() # compiling if ncores>1: strcores='-j'+str(ncores) command = ['make',strcores] logfile = self.pad+'/Build/PADcompilation.log' result, out = ShellCommand.ExecuteWithLog(command,logfile,self.pad+'/Build') time.sleep(1.); # Checks and exit if not result: logging.getLogger('MA5').error('Impossible to compile the PAD. For more details, see the log file:') logging.getLogger('MA5').error(logfile) return False return True
def Run(self,program,args,folder,silent=False): # shell command commands = ['./'+program] commands.extend(args) self.logger.debug("Command: "+" ".join(commands)) # logfile logfile = os.path.normpath(folder+'/'+program+'.log') self.logger.debug("LogFile: "+logfile) # call result, out = ShellCommand.ExecuteWithLog(commands,logfile,folder,silent) # return result if not result and not silent: self.logger.error('impossible to run the project. For more details, see the log file:') self.logger.error(logfile) return result
def RunPAD(self, PADdir, eventfile): ## input file if os.path.isfile(PADdir + '/Input/PADevents.list'): os.remove(PADdir + '/Input/PADevents.list') infile = open(PADdir + '/Input/PADevents.list', 'w') infile.write(eventfile) infile.close() ## cleaning the output directory if not FolderWriter.RemoveDirectory( os.path.normpath(PADdir + '/Output/PADevents.list')): return False ## running command = ['./MadAnalysis5job', '../Input/PADevents.list'] ok = ShellCommand.Execute(command, PADdir + '/Build') if not ok: self.logger.error('Problem with the run of the PAD on the file: ' + eventfile) return False os.remove(PADdir + '/Input/PADevents.list') return True
def LaunchInteractiveMatplotlib(self): # Commands theCommands = [sys.executable, 'all.py'] # Log file name logname = os.path.normpath(self.histo_path + '/matplotlib.log') # Execute logging.getLogger('MA5').debug('shell command: ' + ' '.join(theCommands)) ok, out= ShellCommand.ExecuteWithLog(theCommands,\ logname,\ self.histo_path,\ silent=False) # return result if not ok: logging.getLogger('MA5').error( 'impossible to execute MatPlotLib. For more details, see the log file:' ) logging.getLogger('MA5').error(logname) return ok
def Configure(self): # KNOWn DELPHES ISsues: GENERATE ISSUES BECAuse IT USES TCSLSH COMMAND # Input theCommands = ['./configure'] logname = os.path.normpath(self.installdir + '/configuration.log') # Execute self.logger.debug('shell command: ' + ' '.join(theCommands)) ok, out= ShellCommand.ExecuteWithLog(theCommands,\ logname,\ self.installdir,\ silent=False) # return result if not ok: self.logger.error( 'impossible to configure the project. For more details, see the log file:' ) self.logger.error(logname) return ok
import time import atexit from flask import Flask from flask import Response from flask import render_template from flask import stream_with_context from shell_command import ShellCommand APP = Flask(__name__) LOOP = asyncio.get_event_loop() asyncio.set_event_loop(LOOP) atexit.register(LOOP.close) cmd = ShellCommand('tail', '/var/log/syslog') cmd.execute() @APP.route('/shell') def shell(): def events(): ll = [] def handler(item): ll.append(item) cmd = ShellCommand('tail', '/var/log/syslog') yield 'event: ping\n' yield 'data: Executing "{}"\n\n'.format(cmd)