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
  • 79,293
alkabary
  • 1,479
  • 5
  • 19
  • 37
  • 4
    Quite frankly, your first error is scripting in tcsh :). Even the tcsh FAQ itself links to the famous essay 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
  • 333,661
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)'