まあ、これは私の台本です。私のシステムはsysctl.confに設定されています。
infile = open('sysctl.conf')
outfile = open('sysctl.conf.new', 'w')
replacements = {'Net.ipv4.icmp_echo_ignore_all' :'1',
'Net.ipv4.icmp_echo_ignore_broadcasts' :'1',
'Net.ipv4.ip_forward' : '0',
'Net.ipv4.tcp_syncookies':'1',
'Net.ipv4.conf.all.rp_filter': '1',
'Net.ipv4.conf.all.Log.martiansd':'1',
'Net.ipv4.conf.all.Secure_redirects' : '1',
'Net.ipv4.conf.all.Send_redirects' : '0',
'Net.ipv4.conf.all.Accept_Source_Route': '0',
'Net.ipv4.conf.all.Accept_redirects':'0',
'Net.ipv4.tcp_max_syn_backlog': '4096',
}
for line in infile:
if '#' in line:
pass
elif '=' in line:
w = line.split('=')
for var, value in replacements.iteritems():
if var in w[0]:
line=line.replace(w[1],value)
outfile.write(line)
infile.close()
outfile.close()
スクリプトはうまくいきますが、問題があります。代替パラメータがsysctl.confにない場合、新しい設定ファイルに追加されません。私の値に存在するパラメータのみを変更します。設定にすべてのパラメータを追加するか、すでに存在する場合は変更したいと思います。どうすればいいですか?
私はこれが簡単になることを知っていますが、ここに閉じ込められています。
答え1
私は次のようにすることができます:
testing = True
if testing: ##################################################################
infile = '''
key0=0
key1=1
key1 = 1
key2=2 # comment1
#key3=3
#key4=4
#key5=5 # comment
#key6=6 # comment
key7=7
key8 = 8
'''
infilelines = infile.split('\n')
class of():
def write(self, s):
print s
def close(self):
pass
outfile = of()
replacements = {
'key1' :'11repl',
'key2' :'22repl',
'key3' :'33repl',
'key4' :'44repl',
'key5' :'55repl',
'key6' :'66repl',
}
else: #########################################################################
# as proposed by csny, only open file quickly
# (file is closed after with statement)
with open('sysctl.conf') as infile:
infilelines = infile.readlines()
outfile = open('sysctl.conf.new', 'w')
replacements = {'Net.ipv4.icmp_echo_ignore_all' :'1',
'Net.ipv4.icmp_echo_ignore_broadcasts' :'1',
'Net.ipv4.ip_forward' : '0',
'Net.ipv4.tcp_syncookies':'1',
'Net.ipv4.conf.all.rp_filter': '1',
'Net.ipv4.conf.all.Log.martiansd':'1',
'Net.ipv4.conf.all.Secure_redirects' : '1',
'Net.ipv4.conf.all.Send_redirects' : '0',
'Net.ipv4.conf.all.Accept_Source_Route': '0',
'Net.ipv4.conf.all.Accept_redirects':'0',
'Net.ipv4.tcp_max_syn_backlog': '4096',
}
for line in infilelines:
# if # at the beginning (neglecting whitespaces): its only a line comment
# write it directly to outfile and continue with next line
if len(line.strip())==0 or line.strip()[0] == '#':
outfile.write(line.strip())
continue
# try if this is a properly formated line like: key=val
try:
key, val = line.split('=')
key = key.strip()
val = val.strip()
# something stange happend: It was not a proper key=val line
# dont modify anything, just write the line to the new file
except ValueError:
# or comment out outfile.write to delete the strange line
# from the output config file
outfile.write(line)
continue
# maybe you want to allow line end comments like: key=val # comment?
# lets try if the value actually contains a comment
try:
val, comment = val.split('#')
comment = '# ' + comment.strip()
val = val.strip()
# there is no comment at the end of the line
# (the val.split() returns only one value and thus the unpacking fails with:
# ValueError: need more values to unpack)
except ValueError:
comment = ''
# replace the val if the according key in the `replacements` dict
# with the value stored in the key
# otherwise don't change anything
if key in replacements.keys():
val = replacements[key]
# put together the new line for the output file
line = '%s=%s %s' % (key, val, comment)
outfile.write(line)
outfile.close()
コードのコメントをご覧ください。これは構成ラインを分離し、キーが辞書に存在する場合は値を変更し、最後に出力ファイルに印刷するためにラインを再組み立てします。行末にコメントを追加することもできます。
答え2
コードに関するいくつかのコメント:
- 存在しない場合、「置換」から構成を簡単に挿入するには、「交換」のファイルの各行を繰り返すのではなく、各「交換」に対してファイルの各行を繰り返すことをお勧めします。これにより、行に代替キーが見つからない場合は、新しい構成行を構成して作成します。
- 私はむしろ「readlines()」を使用してsysctl.confファイルを開いたままにする代わりにsysctl.confを閉じてsysctl.confファイルを解放したいと思います。他のプロセスがsysctlを使用している場合、それを実行すると構成が破損する可能性があります。
- 「#」またはキー=値で始まる行を含むsysctl.confファイルを解析しています。値が存在する場合、説明はありません。