Hey! What's been up guys? I usually don't post things like this here. I always wish to separate such technical stuff from my personal life. But today, I came across an interesting phenomenon.
I work on CSHELL. Probably the most unpopular shell these days. Anyone would recommend not to use it. Because of the absurdness of its syntax and quoting. For an example: Top 10 reasons to avoid using CShell
My intention was to write a generic wrapper script that I could use to invoke another script that supposedly attempts to update a database and in the unlikely event of failing to do so, the wrapper would wait for a while and retry again. I thought of this approach as we had been facing some database locking issues and some data that was supposed to updated wasn't getting updated. And this was causing even more problems for us. Since some of our systems rely on this data. By the way, to give you an idea of the locking problem, let me tell you, we have one MySQL database, that is updated by several processes running on 7 different boxes. Now you can understand the number of processes trying to access the database at similar intervals.
#!/bin/csh set argv = `getopt -s tcsh -o r:f: -- $*` if ($status != 0) then echo "Error" exit 1 endif set totalNumberOfRetries = 10 set sleepTime = 30 while (1) switch($1) case -r: set totalNumberOfRetries = "$2" echo "INFO: Number of retries: $totalNumberOfRetries" shift; shift breaksw case -f: set sleepTime = "$2" echo "INFO: Retry frequency in seconds: $sleepTime" shift; shift breaksw case --: shift break default: echo "Unknown option. Terminating" ; exit 1 endsw end echo $#argv set check = $argv[1] echo $check shift if ( $#totalNumberOfRetries > 0 ) then eval eval set retryCount = $totalNumberOfRetries while ( $retryCount >= 0) echo "invoking $check with $argv" eval eval "$check $argv" if ($retryCount != 0) then echo "INFO: $retryCount retries remaining" echo "INFO: Going to wait $sleepTime seconds before next attempt" eval sleep $sleepTime endif @ retryCount -- end endif
I'll do the indentation when I get time.
Did you notice those lines where there are two eval commands? Is it normal to see something like that? For those familiar with CShell it might be normal. I'm just getting familiar. So I felt it quite weird. I have been working on CSHELL for around 6 months. But never came across a requirement where I had to use something this sort. What actually happens in the code above is that, the getopts converts the argument list into single quoted strings separated by white space. now my script name needn't be the full path of a script. But could also be an alias. I hope you know what an alias is. If not, it is just a short name to call a script. We usually have aliases for tools and we call them in different programs. So here this wrapper would invoke a tool with its arguments. And the tool's alias would be passed into the program. So suppose the alias is testArgPass to run a script 'csh /home/users/egk/checkArgPass1.csh'. Then if I type eval 'testArgPass' $argsList in a shell script, it would eval the testArgPass and expand it to the full 'csh ....' and then substitute the list of arguments and execute it.
But getopts makes things a little more complicated. getopts converts the whole thing into something like this
"'testArgPass'"
which can't be parsed by one single eval. Because quoting works really weird in CSHELL. You can find a variety of sources talking about the absurd characteristics of Cshell like this one Csh Programming Considered Harmful. So for evaluating the outer quotes you need another eval. And two evals finally succeeds in getting the expanded alias.
I don't think that was of great help. But then if at all you were searching for 'eval and command not found cshell' or something of that sort, and if my blog turns up in the results, then probably you could save a few hours.
Comments
Post a Comment