我需要在IP地址发生变化时更新文本文件,然后再从shell运行一些命令。
创建变量LASTKNOWN =“212.171.135.53” 这是我们编写此脚本时的IP地址。
获取当前的IP地址。它会每天更改。
为新IP创建变量CURRENT。
比较(作为字符串)CURRENT到LASTKNOWN
如果它们相同,请退出()
如果不同,
一个。将包含LASTKNOWN IP地址的旧配置文件(/etc/ipf.conf)“复制”到/ tmp
B.用/tmp/ipf.conf文件中的CURRENT替换LASTKNOWN
C.使用子进程“mv /tmp/ipf.conf /etc/ipf.conf”
D.使用子进程执行“ipf -Fa -f /etc/ipf.conf”
E.使用子进程执行,“ipnat -CF -f /etc/ipnat.conf”
出口()
我知道如何执行第1步到第6步。我堕落在“文件编辑”部分,A - > C.我无法分辨使用什么模块或是否应该编辑文件。有很多方法可以做到这一点,我无法决定最好的方法。我想我想要最保守的一个。
我知道如何使用子进程,因此您无需对此进行评论。
我不想替换整条线;只是一个特定的点缀四边形
谢谢!
答案 0 :(得分: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)
答案 1 :(得分:6)
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()
或类似的替换
注意:代码未经过测试。
答案 2 :(得分:2)
你试图“原子地”更新文件的内容,并且在这个主题上有许多令人愉快的火焰战争。但一般模式是:
1)将新文件写入临时文件,并确保刷新并关闭。
2)使用操作系统的工具将临时文件原子重命名为旧文件。
现在,您根本无法在Windows中自动重命名文件,但听起来您仍然使用类似unix的系统。您使用os.rename()原子重命名。
答案 3 :(得分:2)
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的主要区别:
例如 - fileinput只能逐行编辑,in_pace允许将整个文件读取到内存(如果不大)并修改它。
答案 4 :(得分:1)
最简单的方法可能是使用f = open(文件名,模式)打开文件。然后,使用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.
答案 5 :(得分: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.
这是测试的工作代码,我的东西合并到你的pastebin代码中:
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时使用少一个子进程调用。