6

IPアドレスが変更されるたびにテキストファイルを更新し、その後シェルからいくつかのコマンドを実行する必要があります。

  1. 変数LASTKNOWN="212.171.135.53"を作成します。これは、このスクリプトの作成中に使用したIPアドレスです。

  2. 現在のIPアドレスを取得します。毎日変わります。

  3. 新しいIPの変数CURRENTを作成します。

  4. (文字列として)CURRENTとLASTKNOWNを比較します

  5. それらが同じである場合、exit()

  6. それらが異なる場合、

    A. LASTKNOWNIPアドレスを含む古い構成ファイル(/etc/ipf.conf)を/tmpに「コピー」します。B。/tmp/ipf.confファイルでLASTKNOWNをCURRENTに置き換えます。
    C.サブプロセス"mv/tmp
    /ipf.conf/etc/ipf.conf"を使用するD.サブプロセスexecute"ipf-Fa-f/etc/ipf.conf"
    を使用するE.サブプロセスexecute"ipnat -CF-f"を使用する/etc/ipnat.conf "

  7. 出口()

手順1から6の方法を知っています。「ファイル編集」の部分であるA->Cに分類されます。使用するモジュールや、ファイルをその場で編集する必要があるかどうかがわかりません。これを行う方法はたくさんあるので、最善のアプローチを決めることはできません。私は最も保守的なものが欲しいと思います。

サブプロセスの使い方を知っているので、コメントする必要はありません。

行全体を置き換えたくありません。ただ特定の点線のクワッド。

ありがとう!

4

6 に答える 6

27

その場でファイルを簡単に編集する別の方法は、fileinputモジュールを使用することです。

import fileinput, sys
for line in fileinput.input(["test.txt"], inplace=True):
    line = line.replace("car", "truck")
    # sys.stdout is redirected to the file
    sys.stdout.write(line)
于 2010-03-02T14:43:26.090 に答える
6

/etc/ipf.confでLASTKNOWNをCURRENTに置き換えます

一度にすべて交換

filename = "/etc/ipf.conf"
text = open(filename).read()
open(filename, "w").write(text.replace(LASTKNOWN, CURRENT))

行ごとに置き換える

from __future__ import with_statement
from contextlib import nested

in_filename, outfilename = "/etc/ipf.conf", "/tmp/ipf.conf"
with nested(open(in_filename), open(outfilename, "w")) as in_, out:
     for line in in_:
         out.write(line.replace(LASTKNOWN, CURRENT))
os.rename(outfilename, in_filename)

注:「/ tmp / ipf.conf」は、tempfile.NamedTemporaryFile()または同様のものに置き換える必要が
あります。注:コードはテストされていません。

于 2009-10-18T06:47:31.167 に答える
4

fileinputモジュールには非常に醜いAPIがあり、このタスク用の美しいモジュールを見つけました-in_place、Python 3の例:

import in_place

with in_place.InPlace('data.txt') as file:
    for line in file:
        line = line.replace('test', 'testZ')
        file.write(line)

fileinputとの主な違い:

  • sys.stdoutをハイジャックする代わりに、書き込み用に新しいファイルハンドルが返されます。
  • ファイルハンドルは、readline()だけでなく、すべての標準I/Oメソッドをサポートします。

たとえば、fileinputは行ごとの編集のみが可能で、in_paceはファイル全体をメモリに読み取り(大きくない場合)、変更することを許可します。

于 2018-04-17T08:53:18.900 に答える
2

あなたはファイルの内容を「原子的に」更新しようとしていますが、この件に関しては多くの楽しい炎の戦争がありました。しかし、一般的なパターンは次のとおりです。

1)新しいファイルを一時ファイルに書き込み、フラッシュして閉じていることを確認します。

2)オペレーティングシステムの機能を使用して、一時ファイルの名前を古いファイルにアトミックに変更します。

さて、Windowsでファイルの名前をアトミックに変更することはできませんが、とにかくUNIXライクなシステムを使用しているように聞こえます。os.rename()を使用してアトミックに名前を変更します。

于 2009-10-17T17:47:23.743 に答える
1

おそらく最も簡単な方法は、f = open(filename、mode)を使用してファイルを開くことです。次に、f.readlines()を使用してすべての行を読み取ります(これにより、プログラムの行を表す文字列のリストが返されます)。

次に、これらの文字列を検索してアドレスを見つけ、それを新しい文字列に置き換えることができます(標準の文字列置換、正規表現、または必要なものを使用して)。

最後に、f.writelines(lines)を使用して行をファイルに書き戻すことができます。これにより、行のリストが便利に戻されます。

注:これはこれを行うための効率的な方法ではなく、最も簡単な方法です。お願いします

コード例:

f = open(filename, "r")
lines = f.readlines()

# Assume that change_ip is a function that takes a string and returns a new one with the ip changed): example below
ret_lines = [change_ip(lines) for line in lines]
new_file = open(new_filename, "w")
new_file.writelines(lines)

def change_ip(str):
   ''' Gets a string, returns a new string where the ip is changed '''
   # Add implementation, something like: return str.replace(old_ip, new_ip) or something similair.
于 2009-10-17T17:45:26.213 に答える
0

コメントとpastebinに置いたコードを確認した後、これが実用的な解決策です。まず、ファイル/tmp/iiiipf.confには次のものが含まれています。

Simply a test file 175.48.204.168

And two times 175.48.204.168 on this line 175.48.204.168

Done.

コードを実行した後、ファイル/tmp/iiiipf.confには次のものが含まれます。

Simply a test file 10.73.144.112

And two times 10.73.144.112 on this line 10.73.144.112

Done.

そして、これが私のものをあなたのペーストビンコードにマージしたテスト済みの動作コードです:

import socket
import fileinput
import subprocess
import string
import re

CURRENT = socket.getaddrinfo(socket.gethostname(), None)[0][4][0]
LASTKNOWN = '175.48.204.168'

if CURRENT == LASTKNOWN:
    print 'Nevermind.'
    subprocess.sys.exit()

else:

    cf = open("/tmp/iiiipf.conf", "r")
    lns = cf.readlines()
    # close it so that we can open for writing later
    cf.close()

    # assumes LASTKNOWN and CURRENT are strings with dotted notation IP addresses
    lns = "".join(lns)
    lns = re.sub(LASTKNOWN, CURRENT, lns)  # This replaces all occurences of LASTKNOWN with CURRENT

    cf = open("/tmp/iiiipf.conf", "w")
    cf.write(lns)
    cf.close()

このコードは、構成ファイル内でIPアドレスが複数回使用されている場合でも、必要な処理を実行します。コメント行でも変更されます。

この方法では、/ tmpにコピーする必要はなく、ファイアウォールとNATを再起動するときに使用するサブプロセス呼び出しが1つ少なくなります。

于 2009-10-17T18:37:14.500 に答える