Take the 2-minute tour ×
Server Fault is a question and answer site for professional system and network administrators. It's 100% free, no registration required.

I have an old method of killing idle mosh-server processes, which doesn't work on my new VPS.

Here's the old method, which I run in root's crontab to clean up mosh processes that have been idle for 10+ days:

for tty in `w -sf | grep -P '\d\ddays mosh-server' | cut -c 10-15`; do kill -9 `ps -o pid= -t $tty`; done

The problem is that on the new VPS, these processes don't have TTYs, so I can't match by TTY and kill mosh that way. Here's what I've got so far (BTW, the new VPS is running kernel 3.2 on Debian wheezy, the old one was the prior Debian edition).

for loginday in `w | grep -P '\d\ddays.* mosh-server' | cut -c 34-40 | sed 's/^\([0-9]*\)\([a-zA-Z]*\).*$/\2 \1/'`; do echo $loginday; done

I'm trying to get the login day from 'w' and correlate it later with info from 'ps':

ps -C mosh-server -o bsdstart

Thus, I could correlate any idle mosh-server sessions started on the same day as login (which is probably 99.9% of them in the wild) and kill them THAT way, using 'ps' to get the pid.

However, 'w' outputs login day thusly:

03Oct13

Which I cut to simply "03Oct".

And 'ps' outputs thusly:

Oct 3

You can see in the above sed command, which is the part that isn't working, I'm trying to take in "03Oct" and output "Oct 03" (I'll deal with the zeroes when I get this working) and I cannot for the life of me get sed to work inside the for loop when it seems to work when I test it with 'echo':

echo 03Oct | sed 's/\([0-9]*\)\([a-zA-Z]*\).*/\2 \1/'

What's mangling the sed command once I paste it into the for loop?

Better yet, is there a better or less hacky way to do this? Given that detached idle mosh-server processes don't have TTYs on Linux 3.2 that I can easily associate? Edit: Also, on systems with libutempter installed, mosh-server will write information to utmp that I suspect would be useful, but I don't know how to get at it.

share|improve this question
add comment

1 Answer

Your echo test is different from your loop test in two significant ways:

  • There's no white space around the date
  • the regex lacks anchors

Part of the reason your loop test isn't working is that you're not taking the white space into account. Another reason is that you're using the * quantifier which means "zero or more" and has the affect that you want some digits, but not really. To fix that you could use the + quantifier which means "one or more". We'll use that for the alpha characters. However, since you want to eliminate the leading zero, we can take a little different direction with the digits.

Since GNU sed supports extended regexes we can eliminate escaping all those special characters plus the ones I've added. Note, however, that the -r option is not portable. Also, I'm substituting the named character class for alphabetic characters to make the regex a little more readable and to make it compatible with languages with different character sets.

sed -r 's/^ *((0)|([1-9]))([0-9])([[:alpha:]]+).*$/\5 \3\4/'

The leading zero is being captured in group 2 and is being discarded. Group 1 is the leading digit of the two-digit number. Group 3 is empty when group 2 contains a zero (because of the alternation created using the pipe character).

As far as utmp goes, does last mosh-server output anything useful for you (with libutempter installed)?

Please also see Process Management to see if you find anything useful.

share|improve this answer
    
So, I'm now doing this after puzzling through it on the command line to pick apart how your solution works: for loginday in `w | grep -P '\d\ddays.* mosh-server' | cut -c 34-40 | sed -r 's/^ *((0)|([1-9]))([0-9])([a-zA-Z]+).*$/\5 \3\4/'`; do echo $loginday; done and it prints Oct and 03 on separate lines. I've never figured out how to stop that when it happens. –  Gordon Morehouse Nov 22 '13 at 16:05
    
last seems to search on wtmp by default on Debian; last -f /run/utmp mosh-server outputs a blank line, then the date upon which utmp starts. –  Gordon Morehouse Nov 22 '13 at 16:08
    
Bash tips: Always quote variables for output. You should use while read -r instead of for with pipelines. Use $() instead of backticks for readability and nestability. Your grep | cut | sed can be combined into one sed or awk. BashFAQs and other pages on that site are an essential resource. –  Dennis Williamson Nov 22 '13 at 17:14
    
@GordonMorehouse: (I forgot to @ you in the previous comment) Oh, and when you use for quote its argument. for x in "$foo" –  Dennis Williamson Nov 22 '13 at 17:55
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.