2
#! /usr/bin/tcsh -f

set ps_output = "`ps -u $user`"
@ i = 2

echo "$ps_output"

set ps_test

while ( $i <= $#ps_output )
    set line = ( $ps_output[$i] )
    if ( $line[4] != "ps" && $line[4] != "tcsh" && $line[4] != "zap" ) then
        set ps_test = ( $ps_test $i )
    endif
    @ i ++
end    

foreach i ( $ps_test )
    set line = ( $ps_output[$i] )
    set process_no = $line[1]
    if ( $line[4] == "HAL9000" || $line[4] == "HALos" || $line[4] == "HALshell" || $line[4] == "HALkeyboardDriv" || $line[4] == "HALdisplayDrive" || $line[4] == "HALdiskDriver" ) then
        kill -9 $process_no
    endif
end


exit 0

So I keep getting the set no match error in my script, but i couldn't find which set is responsible for that , I mean even when I commented out set ps_test , I still get a no set match, is there a way to fix this

Anthon
  • 78,313
  • 42
  • 165
  • 222
alkabary
  • 1,429
  • 5
  • 19
  • 37
  • 4
    Quite frankly, your first error is scripting in tcsh :). Even the [`tcsh` FAQ](http://www.tcsh.org/go?action=browse&diff=1&id=FAQ&revision=29) itself links to [the famous essay](http://www.faqs.org/faqs/unix-faq/shell/csh-whynot/) on why the csh family of shells shouldn't be used for scripting. That said, the way to debug this sort of thing is to add `echo` statements everywhere and see what values your variables are taking. In my case, it choked on `ps` lines containing `?` which, I think, was treated as a glob and changed the value I was setting. – terdon Jan 22 '16 at 10:40
  • 1
    What @terdon said. I suspect you're running into a case of accidental globbing, though. Try adding `set noglob` to the top of the script. – Martin Tournoij Jan 22 '16 at 16:21
  • You'll get this error if the output from `ps` contains a filename globbing pattern that does not match any names. Re-run your script with `tcsh -x` to further debug. – Kusalananda Jun 20 '21 at 10:13

2 Answers2

1

You'll get that error from the set in the first loop,

set line = ( $ps_output[$i] )

... if the output from ps contains words that are shell globbing patterns without matches (for example ?? when there is no files with a two-character filename in the current directory).

A better (as in safer) way of doing what you are attempting to do is to use pkill as Craig Small is showing in their answer, or, slightly more readable,

pkill -x -u $user HAL9000 HALos HALshell HALkeyboardDrv HALdisplayDrive HALdiskDriver

(the -x forces an exact match across the whole command name, not just any substring of the name), or simply

pkill -u $user '^HAL'

to signal any process whose name starts with the substring HAL belonging to the $user user.

Related:

Kusalananda
  • 320,670
  • 36
  • 633
  • 936
0

An alternative is to use pkill on one line either on the command line or in a script.

pkill -9 -u $USER '(HAL9000|HALos|HALshell|HALkeyboardDrv||HALdisplayDrive|HALdiskDriver)'
Craig Small
  • 923
  • 6
  • 8