#!/usr/bin/python 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.')
#!/usr/bin/python import os, shutil, parse, safe, apachehost from random import Random tpl_suffix = '.nano.php' default_title = 'Page title' if __name__ == '__main__': parse.parser.usage = '%prog TEMPLATE [DEST]' parse.shovel({'name': 'force', 'help': 'Overwrite DEST if exists.', 'short': 'f', 'default': False}, {'name': 'title', 'help': 'Set page title', 'short': 't', 'default': default_title}) if len(parse.arguments) < 2: safe.quit('Please, provide host name, template name and destination filename.\n' + parse.parser.format_help(), 1) # check if template exists src = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'templates', parse.arguments[1] + tpl_suffix) if not os.path.isfile(src): safe.quit('There is no template {0} in templates folder ({1})'.format(parse.arguments[1], src), 1) # compose destination path 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'
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'])
(главная программа) ... with safe.open(hosts_file, 'r') as f: try: print ''.join(f) except IOError: safe.quit('Файл {0} открылся, но при чтении произошёл сбой.', hosts_file) ... (Примечание: в своих программах и своём модуле safe я использую декораторы, проверяющие тип данных.) Что дальше? Во-первых, трассировка исключения содержит очень много полезной информации, намного больше, чем та, что печатается Питоном. Полезно будет сделать метод, сохраняющий эти данные куда-либо в файл, чтобы пользователь мог отправить его разработчику. Резюме Теперь на множество типичных случаев у нас есть 4 способа обрабатывать исключения: вынести действия в новый метод и декорировать его методом wrap
#!/usr/bin/python import os, parse, safe, apachehost parse.parser.usage = '%prog SERVERNAME [options]' parse.shovel({'name': 'docroot', 'help': 'Server\'s document root. Default: /var/www/SERVERNAME/public_html', 'short': 'd', 'default': '/var/www/{0}/public_html/'},\ {'name': 'admin', 'help': 'Admin\'s contact email', 'default': 'webmaster@localhost', 'short': 'a'},\ {'name': 'override_docroot', 'help': 'AllowOverride for DocumentRoot', 'default': 'All'},\ {'name': 'override_cgi', 'help': 'AllowOverride for cgi-bin', 'default': 'All'},\ {'name': 'host_template', 'help': 'Template for host configuration (./config.template by default)', 'default': os.path.join(os.path.dirname(os.path.realpath(__file__)), 'templates', 'config.template')}) if __name__ == '__main__': if len(parse.arguments) < 1: # 1 argument (server name) is required safe.quit(parse.parser.format_help()) apachehost.create(parse.options, parse.arguments)