Como alterar meu script para substituir e adicionar nova variável em uma configuração?

2

Bem, este é o meu roteiro. É para configurar meus sistemas 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()

Este script funciona bem, mas há um problema. Se algum dos parâmetros em substituição não estiver presente em sysctl.conf, ele não irá adicioná-lo no novo arquivo de configuração. Ele apenas modifica os parâmetros presentes com meus valores. Eu quero adicionar todos os parâmetros na configuração ou alterar se eles já estão presentes. Como fazer isso?

Eu sei que deve ser fácil, mas estou preso aqui.

    
por Shaels 22.07.2014 / 14:32

2 respostas

2

Eu provavelmente faria algo assim:

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()

Veja os comentários no código. Isso desmontará a linha de configuração, alterará o valor se a chave existir no dict e, finalmente, passará a linha a ser impressa no arquivo de saída. Isso também permite comentários nos finais de linha.

    
por 22.07.2014 / 15:08
1

Poucos comentários sobre seu código:

  1. Se você quiser inserir facilmente a configuração de "substituições", se ela não existir, considere iterar cada "substituição" nas linhas do arquivo em vez de cada linha do arquivo sobre "substituições". Desta forma, se você não encontrar nenhuma chave de substituição nas linhas, construa e escreva uma nova linha de configuração.
  2. Eu preferiria usar "readlines ()" e fechar sysctl.conf para liberar o arquivo sysctl.conf em vez de mantê-lo aberto. Se outros processos usarem sysctl, enquanto você estiver executando isso, isso poderá prejudicar suas configurações.
  3. Você está analisando o arquivo sysctl.conf, que contém linhas que começam com "#" ou como key = value. nenhum comentário depois que os valores existirem.
por 22.07.2014 / 16:03

Tags