2015-04-23 76 views
13

因此,今天,2015年4月23日,互联网号码分配机构已经下令使用port 6379Redis,确实是一个非洲的日子!将Redis添加到/ etc/services最优雅的方式是什么?

我想COM·MEM·O·率通过添加以下行到我的/etc/services文件这辉煌的时刻:

redis  6379/tcp 

什么会去了解它的最佳方式?通过最好的,我的意思是,当然,以下内容:

  1. 不用说,新行应在适当的地方(我的系统上IEG下的编号分配块,gnutella-rtr 6347/udp后右)插入
  2. 我“已经考虑使用各种文本编辑器,但感觉出
  3. 理想的地方,解决方案应该是一个拷贝pastable一个班轮
  4. 我可以想象的awk脚本,能做到这一点,但我在寻找对于更多的东西,有一定的感觉

更新重新@Markus' sed建议:恐怕这个问题是应用上不一定具有相同的/etc/services文件,以便其他系统中,这个‘补丁’,扩大对点#1以上,解决方案必须确保无论文件中的前一个服务的具体情况如何,订单都会保留。

更新2:有几点似乎对状态很重要 - a)虽然不是强制性的,但解决方案的长度(或缺少)是其优雅性的重要组成部分(类似于外部依赖性[即缺乏这些]); b)我/我们假设/etc/services是排序的,但是当它不是时会发生什么会很有趣。 c)假定您拥有root权限,并且要小心rm/-rf命令。

回答

8

排序单行将其放在合适的位置:

echo -e "redis\t\t6379/tcp" | sort -k2 -n -o /etc/services -m - /etc/services

+1

我知道我应该从一开始就进入内部;)尽管如此 - 在一天结束时没有偏袒,只有最好的答案才能赢。绝对是最短的答案 - 加分。 '-m'标志稍微给了我一些hibbie-jibbies - 如果/ etc/services没有被分类开始(即所有答案都是非标准的,有效的疑问)。无论如何,我建议你编辑答案并删除'sudo' - 无论如何,没有人对此产生任何困扰;) –

+2

'-m'只是为了确保这些注释行不会移动。未排序的服务将保持不排序。 'sudo'?你在哪里看到的? :) –

1
sed -i '/6347\/udp/a redis  6379\/tcp' /etc/services 

祝你好运!

更新

sed -i '/6347\/udp/a redis \t\t 6379\/tcp' /etc/services 

看起来更好......

更新2

sed -i ''"$(echo $(echo $(grep -n $(awk {'print$2'} /etc/services | awk -F "/" '$1<6379'{'print$1'} | tail -1) /etc/services | awk -F ':' {'print$1'}|tail -1) + 1)|bc)"'i redis \t\t 6379\/tcp' /etc/services 
+0

Heya @Markus - 你和Markus一样吗? ;)这基本上是我想到的,但请参阅该问题的更新。 –

2

如何Python脚本,伊塔马尔?

它在提取端口号(在代码中称为索引)的概念上工作,如果我们高于6378但尚未打印我们的Redis线,则将其打印出来,然后将该哨兵标记为true并仅打印所有行(包括我们正在使用的那个)之后。

#!/usr/bin/python 
lines = open("/etc/services").readlines() 
printed=False 
for line in lines: 
    if printed: 
     print line.rstrip() 
     continue 
    datafields = line.split() 
    if line[0] == "#": 
     print line.rstrip() 
    else: 
     datafields = line.split() 
     try: 
      try: 
       index,proto = datafields[1].split("/") 
       index = int(index) 
      except: 
       index,proto = datafields[0].split("/") 
       index = int(index) 
      if index > 6378: 
       if not printed: 
        print "redis   6379/tcp #Redis DSS" 
        printed = True 
      print line.rstrip() 
     except: 
      print datafields 
      raise 

在我的文件中的相关部分,用于比较:

gnutella-rtr 6347/tcp # gnutella-rtr 
#       Serguei Osokine <[email protected]> 
#    6348-6381 Unassigned 
redis   6379/tcp #Redis DSS 
metatude-mds 6382/udp # Metatude Dialogue Server 
metatude-mds 6382/tcp # Metatude Dialogue Server 

注意上面Redis的行的范围。没有打破范围这对我来说是一个可行的解决方案。你可能打破范围,但IMO这工作得很好。对于简单,优雅的脚本来说,分割范围似乎有点多。特别是考虑到大多数服务文件没有未列出的未分配范围(这在OS X上) - 而且它们无论如何都在注释中。

UPDATE

如果你不关心本地文件,它的意见,这可以让你所有当前分配的端口未保留或丢弃-ED: curl -s http://www.iana.org/assignments/service-names-port-numbers/service-names-port-numbers.csv| awk -F',' '$4!~/(Discard|Unassigned|Reserved)/ && $1 && $2+0>0 && $1!~/FIX/ {printf "%-16s\t%s/%s\t#%s\n", $1,$2,$3,$4}' > /etc/services

的FIX测试是因为其中一些行嵌入了新行 - 这可能会让awk感到痛苦。

+0

嘿,可以在Go中实现它,然后运行编译后的二进制文件可以是一行代码。 ;) –

+1

这个绝对是最强大和最可扩展的解决方案 - 唯一的缺点是使用滑稽的脚本语言,虽然是当前最喜欢的编码选择,但是我不愿意管理该项目的范围。一个编译好的二进制文件,无论是Go还是ANSI C,虽然是最好的表现者,但它并不能与ehm挑战的精神产生共鸣。 –

+0

它是一个依赖关系,你会发现它已经安装在几乎每个使用/ etc/services的现代操作系统上。 ;)awk在任何地方都不是相同的 - 这就是为什么我现在有OS X的awk脚本(它使用“一个真正的awk”)和Linux的不同的脚本(在某些情况下,我安装了一个不同的脚本awk在Linux中处理它)。 :/简单的东西通常是一样的,但一旦你进入更复杂的东西,它可以打破。 sed也是如此。 –

2

幂等AWK的一行,为了插入6379将是:

awk -v inserted=0 '/^[a-z]/ { if ($2 + 0 == 6379) { inserted=1 }; if (inserted == 0 && $2 + 0 > 6379) { print "redis\t\t6379/tcp"; inserted=1 }; print $0 }' /etc/services > /tmp/services && mv /tmp/services /etc/services 
+0

完美 - 我的第一选择atm :) –

1

我喜欢的置换sed,所以我把它与awk中的下一行搜索结合起来services

R="redis\t\t6379/tcp\t\t\t# data structure server" N=$(awk '{if($2+0 == 6379) exit(1);if ($2+0 > 6379) {print $0;exit(0)}}' /etc/services) && sed -i "s~$N~$R\n$N~" /etc/services 
+1

足够sed! Awksome :) –

2

真正的男人不使用SED/AWK :)在打击回答我的问题的规则

TMP_SERVICES=/tmp/services.$RANDOM 

while read line 
do 
    printf %b "$line\n" >> $TMP_SERVICES 
    if [[ $line == *"6347/udp"* ]]; then 
    printf %b "redis\t\t6379/tcp\n" >> $TMP_SERVICES 
    fi 
done<"/etc/services" 

mv -fb $TMP_SERVICES /etc/services 
+0

那么说,但真正的fanboys呢? ;)我唯一的担心 - 你专门针对'6347/udp',这可能会在某些系统上出现问题。 –

+1

Idk,不应该/ etc/services被标准化吗?至少在所有系统上都有6347的地方... P.S惊讶地发现没有人想到curl -o http://my/script.sh | bash的方法呢:) – cryptid

+0

它是标准化的......就像电气插座一样,任何人都可以编辑她/他自己的东西 –

3

无 - 这一个使用Redis的专门

cat /etc/services | redis-cli -x SET services; redis-cli --raw EVAL 'local s = redis.call("GET", KEYS[1]) local b, p, name, port, proto; p = 1 repeat b, p, name, port, proto = string.find(s, "([%a%w\-]*)%s*(%d+)/(%w+)", p) if (p and tonumber(port) > tonumber(ARGV[2])) then s = string.sub(s, 1, b-1) .. ARGV[1] .. "\t\t" .. ARGV[2] .. "/" .. ARGV[3] .. "\t\t\t# " .. ARGV[4] .. "\n" .. string.sub(s, b, string.len(s)) return s end until not(p)' 1 services redis 6379 tcp "remote dictionary server" > /etc/services 

格式化Lua代码:

local s = redis.call("GET", KEYS[1]) 
local b, p, name, port, proto 

p = 1 
repeat 
    b, p, name, port, proto = string.find(s, "([%a%w\-]*)%s*(%d+)/(%w+)", p) 
    if (p and tonumber(port) > tonumber(ARGV[2])) then 
     s = string.sub(s, 1, b-1) .. ARGV[1] .. "\t\t" .. ARGV[2] 
     .. "/" .. ARGV[3] .. "\t\t\t# " .. ARGV[4] .. "\n" 
     .. string.sub(s, b, string.len(s)) 
     return s 
    end 
until not(p) 

注:一个类似的挑战(https://gist.github.com/jorin-vogel/2e43ffa981a97bc17259#comment-1440996)已经启发了这个答案。我选择了一个纯粹的Lua脚本方法,而不是利用Sorted Sets ...虽然我可以:)

相关问题