有点麻烦试图让以下工作。
我有一个包含hostname:timestamp
的文件,如下所示:
hostname1:1445072150
hostname2:1445076364
我正在尝试创建一个bash脚本来查询此文件(使用cron作业)来检查时间戳是否超过1小时,如果是,请删除该行。 下面是我到目前为止,但它似乎没有删除文件中的行。
#!/bin/bash
hosts=/tmp/hosts
current_timestamp=$(date +%s)
while read line; do
hostname=`echo $line | sed -e 's/:.*//g'`
timestamp=`echo $line | cut -d ":" -f 2`
diff=$(($current_timestamp-$timestamp))
if [ $diff -ge 3600 ]; then
echo "$hostname - Timestamp over an hour old. Deleting line."
sed -i '/$hostname/d' $hosts
fi
done <$hosts
我设法让时间戳部分正确地识别超过一小时但仍无法从文件中删除时间的主机。
我怀疑这可能是由于while循环保持文件打开但不是100%确定如何解决它。还尝试制作文件的副本并编辑但仍然没有。
替代方案:如果有更好的方法让这个工作并产生相同的结果,我愿意接受建议:)
非常感谢任何帮助。
干杯
答案 0 :(得分:2)
脚本中的问题只是这一行:
sed -i '/$hostname/d' $hosts
单引号内的变量未扩展为其值, 所以该命令试图用字面意思替换&#34; $ hostname&#34;,而不是它的值。如果用双引号替换单引号, 变量将扩展到它的值,这就是你需要的:
sed -i "/$hostname/d" $hosts
可以进行改进:
#!/bin/bash
hosts=/tmp/hosts
current_timestamp=$(date +%s)
while read line; do
set -- ${line/:/ }
hostname=$1
timestamp=$2
((diff = current_timestamp - timestamp))
if ((diff >= 3600)); then
echo "$hostname - Timestamp over an hour old. Deleting line."
sed -i "/^$hostname:/d" $hosts
fi
done <$hosts
改进:
((...))
答案 1 :(得分:1)
您要求替代方案 - 使用awk
:
awk -F: -v ts=$(date +%s) '$2 <= ts-3600 { next }' $hosts > $hosts.$$
mv $hosts.$$ $hosts
ts=$(date +%s)
将awk
变量ts
设置为date
的值。该脚本会跳过第二列(第一个冒号后)中的值小于阈值的所有行。如果你愿意,可以在BEGIN块中进行一次减法。确定<=
或<
是否适用于您的目的。
如果您需要知道哪些行已删除,可以添加
printf "Deleting %s - timestamp %d older than %d\n", $1, $2, (ts-3600) >/dev/stderr;
在next
之前打印标准错误信息。如果必须将其写入标准输出,则需要安排将保留行写入具有print > file
的文件作为过滤条件之后的替代操作(将-v file="$hosts.$$"
作为另一对参数传递给awk
)。可以做出的调整是无止境的。
如果文件的大小很大,将文件的相关子部分一次复制到临时文件然后复制到最终文件比在原始代码中多次编辑文件更快。如果文件足够小,则没有问题。