Необходимо было создать скрипт для редактирования файлов настроек приложения, что бы не изменять его вручную.
В скрипте используется модуль ConfigParser (ссылки в конце поста).
Можно вызывать либо с передачей опций (модуль argparce), либо — без опций.
В случае вызова с опциями — можно указать какой файл редактировать, иначе — будет использован файл по умолчанию (default=CONF_DIR + '/external.properties' в parser.add_argument).
Пример файла конфигурации:
[Connection settings] jdbc.main.url = jdbc:oracle:thin:@host1 jdbc.main.username = USER jdbc.main.password = pass [Mail settings] mail.smtp.host=127.0.0.1 mail.smtp.port=25 mail.smtp.on=false mail.cronExpression=0 0/2 * ? * MON-SUN [Import cron expressions] gateKeeper.cronExpression=0 0 5 ? * MON-SUN cleanup.compress.cronExpression=0 0 12 ? * SUN send.mails.to.group.cronExpression = 0 0 12 ? * MON-SUN exc_tckt_d.cronExpression=0 30 22 ? * MON-FRI [Gate keeper settings] gk.homedir=gate_keeper_report sftp.useLocalFileIfAvailable=true sftp.downloadBaseDir=~/download sftp.maxRetryLimit=3 [TCP Report Extract Properties] usePrecalculatedAggregation=true [Other settings] bean.datasource.query_log_wrapper=mainDataSourceWrapper log.client.exception = false time.to.keep.domain=7*12 time.to.keep.uncompress=1 dao.batch.size.max=30
И сам скрипт:
#!/usr/bin/env python
import os
import sys
import re
import logging
import time
import ConfigParser
import argparse
ENV = os.environ['ENV']
CONF_DIR = os.path.join(os.environ['HOME'], 'secure')
LOG = os.path.join(os.environ['HOME'], 'logs/settings.log')
logging.basicConfig(format = '%(filename)s[LINE:%(lineno)d] - %(levelname)-3s [%(asctime)s] %(message)s ', filename=LOG, level=logging.DEBUG)
parser = argparse.ArgumentParser()
parser.add_argument('-f', '--file', default=CONF_DIR + '/external.properties', help='File to edit, default $HOME/secure/external.properties')
parser.add_argument('-s', '--section', help='Block name to edit option in')
parser.add_argument('-o', '--option', help='Option name to edit option in')
parser.add_argument('-v', '--value', help='New value, to set in option from --option')
RES = parser.parse_args()
print("nWorking on %s and using configuration directory %s.n" % (ENV,CONF_DIR))
logging.info('Setting edit started at %s' % (time.ctime()))
def answer(prompt, choice='Yes or no, please!'):
'''Used for user communication, to confirm selected item.
Return True if 'y' and False if 'n' entered.'''
while True:
result = raw_input(prompt)
if result in ('y', 'Y', 'yes', 'Yes'):
return True
elif result in ('n', 'N', 'no', 'No'):
return False
else:
print(choice)
def select_conf(path):
'''Used to select configuration file from directory in CONF_DIR variable.
Return filename without full path.'''
while True:
list = []
for file in os.listdir(path):
list.append(file)
print('%s %s' % ((list.index(file)), file))
try:
res_file = int(raw_input('nPlease, select file to edit: '))
print('You selected: %s' % list[res_file])
except ValueError as e:
print('Please, enter correct value: %sn' % e)
sys.exit(2)
if answer('Is it OK? [y/n] '):
logging.info('Selected %s file to work with.' % list[res_file])
return(list[res_file])
break
def select_section(configfile):
'''Use ConfigParser module to select sections, declared in [] blocks in file.
File takes from select_conf() function.'''
Config = ConfigParser.ConfigParser()
file = os.path.join(CONF_DIR, configfile)
list = []
try:
Config.read(file)
except ConfigParser.MissingSectionHeaderError as e:
print(e)
sys.exit(5)
print('n')
while True:
for section in Config.sections():
list.append(section)
print('%s %s' % ((list.index(section)), section))
try:
res_section = int(raw_input('nPlease, select section to edit: '))
print('You selected: %s' % list[res_section])
except ValueError as e:
print('Please, enter correct value: %sn' % e)
sys.exit(3)
if answer('Is it OK? [y/n] '):
logging.info('Selected %s section to work with.' % list[res_section])
return(list[res_section], file)
break
def write_changes(file, section, option, value):
file = os.path.join(CONF_DIR, file)
print('Editing file: %s. Will set section: %s, option: %s, value: %s.n' % (file, section, option, value))
Config = ConfigParser.ConfigParser()
Config.read(file)
Config.set(section, option, value)
with open(file, 'r+') as c_file:
Config.write(c_file)
print('New value assigned successfully.')
logging.info('New value assigned successfully. Finished at %s' % (time.ctime()))
def edit_option(*args):
'''If script called without arguments:
Use $section variable from select_section() function, to set section, to select options from,
and $file variable from select_section() function, to set file, to be edited.
First loop - to set new variable $res_option, where option to be edited saves;
second loop - to set new varaible $new_value, to be saved in $section in $file.
next. in second loop, with ConfigParcer - writing new $new_value in $file.
If called with arguments:
will set RES.file, RES.section, RES.option and RES.value from parser.parse_args()'''
Config = ConfigParser.ConfigParser()
if len(sys.argv) <= 1:
section, file = select_section(select_conf(CONF_DIR))
list = []
Config.read(file)
print('n')
while True:
for option in Config.options(section):
list.append(option)
print('%s %s' % ((list.index(option)), option))
try:
res_option = int(raw_input('nPlease, select option to edit: '))
print('You selected: %s' % list[res_option])
except ValueError as e:
print('Please, enter correct value: %sn' % e)
sys.exit(4)
if answer('Is it OK? [y/n] '):
logging.info('Selected %s option to work with.' % list[res_option])
break
while True:
print('nCurrent value of %s is %s.n' % (list[res_option], Config.get(section, list[res_option])))
logging.info('Current value of %s is %s.' % (list[res_option], Config.get(section, list[res_option])))
new_value = raw_input('Please, set new value for %s: ' % list[res_option])
print('Your new value for %s is %s.' % (list[res_option], new_value))
logging.info('Entered new value %s.' % new_value)
if answer('Is it OK? [y/n] '):
write_changes(file, section, list[res_option], new_value)
break
else:
logging.info('Running optional edit. File: %s; section: %s, option: %s, new value: %s' % (RES.file, RES.section, RES.option, RES.value))
write_changes(RES.file, RES.section, RES.option, RES.value)
if __name__ == "__main__":
try:
edit_option(RES.section)
except KeyboardInterrupt:
logging.info('Exited by KeyboardInterrupt at %s.' % (time.ctime()))
print('n')
sys.exit(0)
Его работа, при вызове без опций:
$ ./setting.py Working on DEV and using configuration directory /home/user/secure. 0 external.DEV.properties-NEW 1 external.properties_2014-11-29-12_44_bak 2 external.properties_2014-11-29-12_45_bak 3 external.properties-30_12_2014 4 test.property 5 external.properties 6 external.properties_encoding_bkp 7 secret.key Please, select file to edit: 4 You selected: test.property Is it OK? [y/n] y 0 Connection settings 1 Gate keeper settings 2 TCP Report Extract Properties 3 Mail settings 4 Import cron expressions 5 Other settings Please, select section to edit: 0 You selected: Connection settings Is it OK? [y/n] n 0 Connection settings 1 Gate keeper settings 2 TCP Report Extract Properties 3 Mail settings 4 Import cron expressions 5 Other settings Please, select section to edit: 0 You selected: Connection settings Is it OK? [y/n] y 0 jdbc.main.url 1 jdbc.main.password 2 jdbc.main.username Please, select option to edit: 0 You selected: jdbc.main.url Is it OK? [y/n] y Current value of jdbc.main.url is host2. Please, set new value for jdbc.main.url: host_new.com Your new value for jdbc.main.url is host_new.com. Is it OK? [y/n] y New value assigned successfully.
Лог:
setting.py[LINE:19] - INFO [2014-12-30 14:00:43,339] Setting edit started at Tue Dec 30 14:00:43 2014 setting.py[LINE:58] - INFO [2014-12-30 14:00:47,948] Selected test.property file to work with. setting.py[LINE:94] - INFO [2014-12-30 14:00:57,852] Selected Connection settings section to work with. setting.py[LINE:130] - INFO [2014-12-30 14:01:02,164] Selected jdbc.main.url option to work with. setting.py[LINE:136] - INFO [2014-12-30 14:01:02,164] Current value of jdbc.main.url is host2. setting.py[LINE:139] - INFO [2014-12-30 14:01:09,916] Entered new value host_new.com. setting.py[LINE:146] - INFO [2014-12-30 14:01:11,260] New value assigned successfully. Finished at Tue Dec 30 14:01:11 2014
Вызов с опциями, без указания файла, который редактировать:
$ ./setting.py -s "Connection settings" -o "jdbc.main.url" -v "besturlever.db.com" Working on DEV and using configuration directory /home/user/secure. Editing file: /home/user/secure/external.properties, section: Connection settings, option: jdbc.main.url, value: besturlever.db.com. New value assigned successfully.
И с указанием файла:
$ ./setting.py -f "test.property" -s "Connection settings" -o "jdbc.main.url" -v "besturlever.db.com" Working on DEV and using configuration directory /home/user/secure. Editing file: /home/user/secure/test.property. Will set section: Connection settings, option: jdbc.main.url, value: besturlever.db.com. New value assigned successfully.
Ссылки по модулю ConfigParser