def find(where, servername): sites = os.path.join(where, 'sites-enabled') for h in (f for f in safe.catch(os.listdir, sites, 'Can\'t list {0} directory') if f[-1] != '~'): # open all files except backup versions '*~'. sitefile = os.path.join(sites, h) with safe.fopen(sitefile) as config: # scan configs. need to close automatically afterwards for l in config: # scan config if parse_line(l)[0:2] == ['ServerName', servername]: # if it's not commented (commented produces ['#', ...] list) yield sitefile break
import os, shutil, parse, safe, apachehost from random import Random parse.parser.usage = '%prog HOST' bitrix_file = 'templates/bitrix8setup.php' parse.shovel({'name': 'installer', 'help': 'Path to bitrix installer script', 'short': 'd', 'default': os.path.join(os.path.dirname(os.path.realpath(__file__)), bitrix_file)}) if __name__ == '__main__': if len(parse.arguments) < 1: safe.quit('Please, provide host name\n' + parse.parser.format_help(), 1) # find apache host and get it's document root try: host = apachehost.find(apachehost.config_dir(), parse.arguments[0]).next() # we need only the first [0] host, since it has precedence in apache except StopIteration: safe.quit('Can\'t find host named {0}'.format(parse.arguments[0]), 1) newname = '{0}.php'.format(Random().randint(10**6, 10**7-1)) docroot = os.path.join(os.path.normpath(apachehost.get(host, 'DocumentRoot')['DocumentRoot']), newname) # copy bitrix8setup.php to a randomly named php file safe.catch(shutil.copy, (parse.options['installer'], docroot), 'Can\'t copy bitrix installer to {1}.') # run default web browser os.system('x-www-browser http://{0}/{1}'.format(parse.arguments[0], newname)) safe.quit('Success! Do installation instructions in your browser.')
dest = os.getcwd() if len(parse.arguments) > 1: dest = os.path.join(dest, parse.arguments[2]) if os.path.isdir(dest): dest = os.path.join(dest, parse.arguments[1].replace(tpl_suffix, '.php')) if dest[-4:] != '.php': dest += '.php' # check if destination doesn't exist or --force is on if os.path.isfile(dest) and not parse.options['force']: safe.quit('Destination file already exists. Use -f/--force to overwrite.', 1) print 'Copying {0} to {1}.' # copy file safe.catch(shutil.copy, (src, dest), 'Can\'t copy template ({0}) to {1}.') print 'Ok.' # replace title with that from command line if parse.options['title'] != default_title: from contextlib import nested import re with nested(safe.fopen(dest), safe.fopen(dest + '.tmp', 'w') as (s, d): for i in s: d.write(re.replace(r'($APPLICATION\\-\\>SetTitle\\(\\s*")[^)]("\\))', '$1{0}$2'.format(parse.options['title'])))
args = [args] try: return method(*args) except exceptions: quit(message.format(*args) + ' '.format(sys.exc_info()[1].args), 1) Теперь можно вызывать любые функции и обрабатывать ошибки, указывая на месте только сообщение об ошибке: safe.catch(os.listdir, '/root', 'Невозможно открыть {0}') safe.catch(shutil.copy, (pathA, pathB), 'Невозможно скопировать {0} в {1}') Такой вид применим, но менее читаем, потому что само действие (os.listdir) находится не в начале строки, а в скобках. Попробуем второй способ — заменить метод, то есть декорировать. Первый метод, catch, нам понадобится, мы его немного перепишем, чтобы можно было вызывать функции с аргументами-ключами, и создадим декоратор, который будет делать обёртку, вызывающую catch: def catch(method, message, exceptions, *args, **kwargs): if not isinstance(message, str):
def create(opts, arguments): """Creates a name-based virtual host (config file), enables it and adds to /etc/hosts.""" if os.getenv('USERNAME') != 'root': safe.quit('I can\'t do anything this way. Sudo me, please!') opts['server'] = arguments[0] # these vars are needed to pass to format() opts['servername'] = arguments[0] + '.' + os.uname()[1] # ...into config.template where = config_dir() if where is None: safe.quit('Apache config directory not found in /etc/') # check if there's no other same named host try: find(where, opts['servername']).next() # need to check if there is ANY file with the same servername safe.quit('A host with ServerName \'{0}\' already exists.'.format(opts['servername'])) except StopIteration: # the only way not to consume the generator (find) is to get .next() and catch the exception pass # need to check if docroot does not exists or is empty opts['docroot'] = opts['docroot'].format(opts['server']) # by default docroot is named as /var/www/host/public_html if os.path.lexists(opts['docroot']): if not os.path.isdir(opts['docroot']): safe.quit('docroot was a file or a link (\'{0}\')'.format(opts['docroot']), 1) if safe.catch(os.listdir, opts['docroot'], 'Document root (\'{0}\') exists but is not accessible.') != []: # try to list the directory. may fail if no access rights safe.quit('docroot parameter was a non-empty directory (\'{0}\')'.format(opts['docroot']), 1) else: safe.catch(os.makedirs, opts['docroot'], 'Can\'t create document root directory \'{0}\'') safe.catch(os.chown, (opts['docroot'], int(os.getenv('SUDO_UID')), int(os.getenv('SUDO_GID'))), 'Can\'t change document root ownership \'{0}\'') # create apache vhost file new_conf = os.path.join(where, 'sites-available', opts['server']) try: with nested(safe.fopen(opts['host_template']), safe.fopen(new_conf, 'w')) as (conf_src, conf_dest): for l in conf_src: conf_dest.write(l.format(**opts)) except KeyError: msg = '\nOops, your template \'{0}\' has placeholders for parameters\nthat were not supplied in the command line:\n - {1}\n'.format(opts['host_template'], '\n - '.join(sys.exc_info()[1].args)) safe.catch(os.rmdir, opts['docroot'], msg + 'Couldn\'t remove document root (\'{0}\')') safe.quit(msg, 1) print 'Host config saved in {0}. '.format(new_conf), # link it couldnt_add_host = 'Couldn\'t add host to enabled hosts (make symlink in \'{0}\')' safe.catch(os.chdir, where + '/sites-enabled', couldnt_add_host) safe.catch(os.symlink, [new_conf, opts['server']], couldnt_add_host) print 'Enabled. ', # add to /etc/hosts with safe.fopen('/etc/hosts', 'a') as hosts: safe.catch(hosts.write, '\n127.0.0.1\t{0}'.format(opts['servername']), 'Can\'t add host to \'/etc/hosts\'.') print 'Added to /etc/hosts. ', # restart apache safe.catch(os.system, '/etc/init.d/{0} restart'.format(serv), 'Couldn\'t restart ' + serv + '({0})') print 'Apache restarted successfully. Host {0} is now available at http://{1}.'.format(opts['server'], opts['servername'])