Create an account

Very important

  • To access the important data of the forums, you must be active in each forum and especially in the leaks and database leaks section, send data and after sending the data and activity, data and important content will be opened and visible for you.
  • You will only see chat messages from people who are at or below your level.
  • More than 500,000 database leaks and millions of account leaks are waiting for you, so access and view with more activity.
  • Many important data are inactive and inaccessible for you, so open them with activity. (This will be done automatically)


Thread Rating:
  • 308 Vote(s) - 3.43 Average
  • 1
  • 2
  • 3
  • 4
  • 5
What's the most elegant way to add Redis to /etc/services?

#1
So today, April 23rd 2015, the Internet Assigned Numbers Authority had decreed the use of [port 6379](

[To see links please register here]

) to [Redis](

[To see links please register here]

), a frabjous day indeed!

I wish to com·mem·o·rate this splendid occasion by adding the following line to my `/etc/services` file:

redis 6379/tcp

What would be the best way to go about it? By best I mean, of course, the following:

1. Needless to say, the new line should be inserted in its proper place (i.e.g. under the Assigned Numbers block, right after `gnutella-rtr 6347/udp` on my system)
2. I've considered the use of various text editors, but it feels out of place
3. Ideally, the solution should be a copy-pastable one-liner
4. I can envision the `awk` script that could do that but I'm looking for something more, a certain je ne sais quoi

*Update re @Markus' `sed` proposal:* I'm afraid the problem would be applying this "patch" on other systems that do not necessarily have the same `/etc/services` file so, expanding on point #1 above, the solution must ensure that regardless the specifics of to-be-preceding service in the file, order is kept.

*Update 2:* a few points that seem important to state - a) while not mandatory, the solution's length (or lack of rather) is certainly an important part of its elegance (similarly for external dependencies [i.e. lack of these]); b) I/we assumed that `/etc/services` is sorted, but it would be interesting to see what happens when it isn't; c) assume that you have root privileges and be careful with that `rm / -rf` command.
Reply

#2
An idempotent awk one-liner that inserts 6379 in order would be:

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
Reply

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

good luck!


# update

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

looks better ...


# update 2

lol

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
Reply

#4
I like the in-place subsitution of sed, so I combine it with an awk search of the next line in `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
Reply

#5
A single line sort that puts it in the right place:

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

#6
Real men don't use 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
Reply

#7
How about a python script, Itamar?

It works on the notion of extracting the port number (called the index in the code) and if we are above 6378 but have not yet printed our Redis line, print it, then mark that sentinel true and just print all lines (including the one we are on) after.

#!/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

The relevant section on my file for comparison:

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

Notice the line above Redis is a range. Short of breaking the range this is a workable solution for me. You *could* break the range but IMO this works just fine. Splitting the range seems a bit much for a simple, elegant script. Especially considering the likelihood most services files don't have the unassigned ranges listed (this is on OS X) - and that they are in a comment anyway.


#UPDATE
If you don't care about the local file and it's comments, this gets you all currently assigned ports which are not Reserved or Discard-ed:
```
curl -s

[To see links please register here]

| 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
```

The FIX test is because some of those lines have embedded newlines - which can be a pain in awk.
Reply

#8
Nothing in the rules against answering my own question - **this one uses Redis exclusively**:

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

Formatted Lua code:

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)

***Note:*** a similar challenge (

[To see links please register here]

) had inspired this answer. I chose a pure Lua script approach instead of leveraging Sorted Sets... although I could :)
Reply



Forum Jump:


Users browsing this thread:
1 Guest(s)

©0Day  2016 - 2023 | All Rights Reserved.  Made with    for the community. Connected through