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
def get(host, params): """Gets dictionary of requested `param`eters from `host` configuration file. Arguments: """ if not isinstance(params, (list, tuple)): params = [params] with safe.fopen(host) as cfg: reader = (parse_line(i)[0:2] for i in cfg) return dict([l for l in reader if l[0] in params])
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'])))
Сохраним файл под именем safe и загрузим из рабочего скрипта: #!/usr/bin/python import safe myfile = '/etc/hosts' with safe.fopen(myfile, 'a') as f: a.write('127.0.0.1 anotherhost') with safe.fopen(myfile, 'r') as f: print ''.join(f) Теперь скрипт красиво остановится, если его выполнить без sudo. Конечно, если сбой произойдёт уже во время записи или чтения, то перехвачен он не будет, но позже мы сделаем защиту и для таких случаев. Методы для более широкого применения
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'])