Input string in J script hangs - input

I write script in J for linux with #!
But script hang. After Control-D script echoed entered value. But normal ENTER only put cursor on new line.
#!/path/jconsole
a =. 1!:1]3
echo a
exit ''

You can't read a single line of text while j is in script mode, but you can schedule something to run the next time j returns to immediate execution mode by setting the immex phrase with 9!:27 and then setting the immex bit to 1 with 9!:29. Here's an example:
#!/usr/bin/env j
NB. demo showing how to make a simple repl in j.
readln =: [: (1!:01) 1:
donext =: [: (9!:29) 1: [ 9!:27
main =: verb define
echo ''
echo 'main loop. type ''bye'' to exit.'
echo '--------------------------------'
while. (s:'`bye') ~: s:<input=:readln'' do.
echo ".input
end.
echo '--------------------------------'
echo 'loop complete. returning to j.'
NB. or put ( exit'' ) here to exit j.
)
donext 'main _'

The thing is that (1!:1)&3 reads till "end of file". In Linux, pressing ctrl-D sends the EOF signal.
If this is not what you're looking for, I'm afraid there there's nothing else but your "ugly trick"
a=. shell 'read foo; echo -n $foo'
as (1!:1)&1 only works during a session for some reason ...

Related

How do I nohup a here document in the background from within a ksh script?

I have a ksh script that comes to a point where it must run a long running command. The long running command is executed via a heredoc in the script presently. I want to throw the command (represented by cat in my samples below) into the background but only after taking its input from the heredoc. Since the "nohup cat.." finishes instantaneously and I see an empty nohup.out file, I am not sure the script is doing what I need it to do, which is to spawn a nohupped version of the heredoc command and exit, leaving the command to run for however long it takes to complete.
I am using cat as the "command" since it too sits there and just waits for console input.
Working version without nohupping:
#!/bin/ksh
cat << EOF
Hello
World
HOw are you!
EOF
Trying to nohup the heredoc:
#!/bin/ksh
nohup cat <<EOF
Hello
World
HOw are you!
EOF
Seems to work, output is going into nohup.out as expected. But now, how to throw that into the background? I tried the below (and many variations of it) :
#!/bin/ksh
nohup cat & <<EOF
Hello
World
HOw are you!
EOF
but, nohup.out is empty, so I am not sure what the above is doing. There is no running "cat" in the background which tells me it ran and completed at least - or maybe didn't run at all. No other variation I can invent for trying to throw the heredoc into the background from my ksh script works.
Any suggestions on a way to achieve this using heredoc?
Here are two options.
You could try wrapping the nohup sequence inside a function, which may look cleaner, and then invoking that function with the trailing ampersand.
Using a function, like this:
#!/bin/ksh
function dostuff
{
nohup cat <<- END
Hello
World
How are you!
END
}
dostuff &
wait
You can also try wrapping the commands to be backgrounded into a grouping { } block, separating each command with a ; inside the brackets, and then backgrounding that block via:
{ nohup cat <<- EOF
...
EOF
; whatever
} &

Declare bash variables inside sql EOF

how to declare variable in bash command. See "?"
I thought we could almost run any bash statement with ! or host in front of line
#!/bin/bash
sqlplus scott/tiger#orcl << EOF
! export v10="Hi" Doesn't work, why?
! echo $v10 Doesn't work, why?
! echo "Done" Works perfectly and also other bash commands
select * from dept; Works perfectly
exit
EOF
Thank you
What #jordanm says "probably" is exactly what is happening. When you specify a host command from within sqlplus, a separate shell process is spawned, the command executed by that process, then that process is terminated and control returns to sqlplus. Any environment variables that are set in that child shell process are good only within it, so when it terminates, they are gone.
As for your specific lines that "work" and "don't work" .. "export v10="Hi" does work but there is no stdout display of the 'export' command, and as explained, that variable v10 ceases to exist once the child process completes and control returns to sqlplus. The "echo $v10" also works, but since that is a new shell process, it has no value for $v10, so there is nothing to echo.
What are you trying to accomplish by setting enviornment variables from within sqlplus?
found it, all I had to do was
<< EOF
whenever sqlerror exit failure rollback
whenever oserror exit failure rollback
#scriptname.sql
EXIT
EOF

How to formulate a Batch script if else clause

I have a simple test to tell me if tomcat8 is running or not. It simply outputs if the service is found or not.
net start | find "Tomcat8" > nul 2>&1
if %ERRORLEVEL%==0 echo "Tomcat8 is running"
if %ERRORLEVEL%==1 echo "Tomcat8 not running"
How could I actually integrate this into a function so I could first test if tomcat8 is running, and if yes - goto end:, and if not - start the service?
eg.
Read if /?:
%ERRORLEVEL% will expand into a string representation of the current
value of ERRORLEVEL, provided that there is not already an
environment variable with the name ERRORLEVEL, in which case you
will get its value instead. After running a program, the following
illustrates ERRORLEVEL use:
goto answer%ERRORLEVEL%
:answer0
echo Program had return code 0
:answer1
echo Program had return code 1
Unfortunately, above code snippet seems to be a bit confusing as displays both messages in case of errorlevel 0. Try next (combined with find return codes):
net start | find "Tomcat8" > nul 2>&1
goto answer%ERRORLEVEL%
:answer0
echo `find` had return code 0, Tomcat8 is running
goto :acorp
:answer1
echo `find` had return code 1, Tomcat8 not running
rem code snippet to start the service here
goto :acorp
:answer2
rem dummy/debugging
echo `find` had return code 2: invalid switch is given
pause
:acorp
Another approach: IF… ELSE …
Parenthesis can be used to split commands across multiple lines. This
enables writing more complex IF… ELSE… commands:
IF EXIST filename.txt (
Echo deleting filename.txt
Del filename.txt
) ELSE (
Echo The file was not found.
)
When using parenthesis the CMD shell will expand [read] all the
variables at the beginning of the code block and use those values even
if the variables value has just been changed. Turning on
DelayedExpansion will force the shell to read variables at the
start of every line.
net start | find "Tomcat8" > nul 2>&1
if %ERRORLEVEL%==1 (
echo "Tomcat8 not running"
rem code snippet to start the service here
) else (
echo "Tomcat8 is running"
)

Powershell piping to variable and write-host at the same time

Hello all and thanks for your time in advance;
I'm running into a slight issue.
I'm running a command and piping it into a variable so i can manipulate the output.
$variable = some command
this normally works fine but doesn't output what's happening to the screen, which is fine most of the time. However occasionally this command requires some user input (like yes or no or skip for example), and since it's not actually piping anything to the command window, it just sits there hanging instead of prompting the user. If you know what to expect you can hit y or n or s and it'll proceed normally.
Is there anyway to run the command so that the output is piped to a variable AND appears on screen? I've already tried:
($variable = some command)
I've also tried:
write-host ($variable = some command)
But neither work. Note that the command running isn't a native windows or shell command and I cannot just run it twice in a row.
To clarify (because i probably wasn't clear)
I've also tried :
$variable = some command : Out-host
and
$variable = some command | out-default
with all their parameters, But the "prompt" from the command (to write y, n, s) doesn't show up.
Being able to pass S automatically would also be acceptable.
Sounds like you need Tee-Object. Example:
some command | Tee-Object -Variable MyVariable
This should pass everything from the command down the pipe, as well as store all output from the command in the $MyVariable variable for you.
You need to give some specific example that doesn't work. I tried this and it works:
function test { $c = read-host "Say something"; $c }
$x = test
I still see "Say something". read-host does not output to standard output so your problem is surprising. Even this works:
read-host "Say something" *> out
=== EDIT ===
Since this is interaction with cmd.exe you have two options AFAIK. First, test command:
test.cmd
#echo off
set /p something="Say something: "
echo %something%
This doesn't work as you said: $x= ./test.cmd
To make it work:
a) Replace above command with: "Say something:"; $x= ./test.cmd. This is obviously not ideal in general scenario as you might not know in advance what the *.cmd will ask. But when you do know its very easy.
b) Try this:
Start-transcript test_out;
./test.cmd;
Stop-transcript;
gc .\test_out | sls 'test.cmd' -Context 0,1 | select -Last 1 | set y
rm test_out
$z = ($y -split "`n").Trim()
After this $z variable contains: Say something: something. This could be good general solution that you could convert to function:
$z = Get-CmdOutput test.cmd
Details of text parsing might be slightly different in general case - I assumed here that only 1 question is asked and answer is on the same line but in any case with some work you will be able to get everything cmd.exe script outputed in general case:
=== EDIT 2 ===
This might be a better general extraction:
$a = gi test_out; rm test_out
$z = $a | select -Index 14,($a.count-5)
$z
$variable = ""
some command | % {$variable += $_;"$_"}
This executes the command, and each line of output is both added to $variable and printed to the console.

Expect script does not work under crontab

I have an expect script which I need to run every 3 mins on my management node to collect tx/rx values for each port attached to DCX Brocade SAN Switch using the command #portperfshow#
Each time I try to use crontab to execute the script every 3 mins, the script does not work!
My expect script starts with #!/usr/bin/expect -f and I am calling the script using the following syntax under cron:
3 * * * * /usr/bin/expect -f /root/portsperfDCX1/collect-all.exp sanswitchhostname
However, when I execute the script (not under cron) it works as expected:
root# ./collect-all.exp sanswitchhostname
works just fine.
Please Please can someone help! Thanks.
The script collect-all.exp is:
#!/usr/bin/expect -f
#Time and Date
set day [timestamp -format %d%m%y]
set time [timestamp -format %H%M]
#logging
set LogDir1 "/FPerf/PortsLogs"
et timeout 5
set ipaddr [lrange $argv 0 0]
set passw "XXXXXXX"
if { $ipaddr == "" } {
puts "Usage: <script.exp> <ip address>\n"
exit 1
}
spawn ssh admin#$ipaddr
expect -re "password"
send "$passw\r"
expect -re "admin"
log_file "$LogDir1/$day-portsperfshow-$time"
send "portperfshow -tx -rx -t 10\r"
expect timeout "\n"
send \003
log_file
send -- "exit\r"
close
I had the same issue, except that my script was ending with
interact
Finally I got it working by replacing it with these two lines:
expect eof
exit
Changing interact to expect eof worked for me!
Needed to remove the exit part, because I had more statements in the bash script after the expect line (calling expect inside a bash script).
There are two key differences between a program that is run normally from a shell and a program that is run from cron:
Cron does not populate (many) environment variables. Notably absent are TERM, SHELL and HOME, but that's just a small proportion of the long list that will be not defined.
Cron does not set up a current terminal, so /dev/tty doesn't resolve to anything. (Note, programs spawned by Expect will have a current terminal.)
With high probability, any difficulties will come from these, especially the first. To fix, you need to save all your environment variables in an interactive session and use these in your expect script to repopulate the environment. The easiest way is to use this little expect script:
unset -nocomplain ::env(SSH_AUTH_SOCK) ;# This one is session-bound anyway
puts [list array set ::env [array get ::env]]
That will write out a single very long line which you want to put near the top of your script (or at least before the first spawn). Then see if that works.
Jobs run by cron are not considered login shells, and thus don't source your .bashrc, .bash_profile, etc.
If you want that behavior, you need to add it explicitly to the crontab entry like so:
$ crontab -l
0 13 * * * bash -c '. .bash_profile; etc ...'
$