In the mac terminal - how can I get arrow keystrokes from stdin? - python

I'd like to browse a terminal dialog menu with the arrow keys (like bash 'dialog')
I would prefer ruby solution, but bash/python could work.
read -n1 input # is not good enough, cause the arrow keys are not regular chars.
Also, the 'read' in mac term doesn't support smaller timeout than 1 second.
Anything?
Thanks,

I am not sure what you are looking for -
a way to simulate key presses to an application, or
a way to generate simple dialog boxes, or
a way to read characters from a keyboard...
However, these may give you some ideas:
For 1: You would probably need to look at the Automator and Applescript
tell application "System Events" to tell process "Finder"
click menu item "New Finder Window" of menu 1 of menu bar item "File" of menu bar 1
end tell
For 2: You could look at Platypus for generating dialog boxes and wrappers around scripts - available here
For 3: The following may do something like you want
#!/bin/bash
#
# Read a key in cbreak mode
stty cbreak -echo; KEY=$(dd bs=1 count=1 2>/dev/null); stty -cbreak echo
#
# If ESCAPE, read next part
if [ $KEY = $'' ]; then
stty cbreak -echo; KEY=$(dd bs=1 count=1 2>/dev/null); stty -cbreak echo
stty cbreak -echo; KEY=$(dd bs=1 count=1 2>/dev/null); stty -cbreak echo
[ $KEY = "A" ] && echo UP
[ $KEY = 'B' ] && echo DOWN
[ $KEY = 'C' ] && echo RIGHT
[ $KEY = 'D' ] && echo LEFT
exit
fi
echo $KEY
I should explain that the if [ $KEY line needs to be typed
if [ $KEY = $'CONTROL-V ESCAPE' ]
i.e. type these 5 things
$
single quote
Control V
Escape
single quote

According to Mark Setchell, minor modification:
#!/bin/bash
# Read a key in cbreak mode
stty cbreak -echo; KEY=$(dd bs=1 count=1 2>/dev/null); stty -cbreak echo
# Check if it's a single alphanumeric char
if $(echo $KEY | grep -q -e "[a-zA-Z0-9]"); then
echo $KEY
exit
# Else we assume escape char (doesn't cover all cases)
else
stty cbreak -echo; KEY=$(dd bs=1 count=1 2>/dev/null); stty -cbreak echo
stty cbreak -echo; KEY=$(dd bs=1 count=1 2>/dev/null); stty -cbreak echo
[ $KEY == 'A' ] && echo UP
[ $KEY == 'B' ] && echo DOWN
[ $KEY == 'C' ] && echo RIGHT
[ $KEY == 'D' ] && echo LEFT
exit
fi

Related

Bash While Loop Continue Despite non 0 return

Im writing a bash script that automates the usage of other python tests (imagedeploy, hydrationwiring). The bash script looks at a .txt list of device names, and then goes down the list and performs 2 things (imagedeploy,hydrationwiring) on each name in the .txt.
What happens is that hydrationwiring test will return a non zero return value at the end, which breaks the loop and ends the script.
I want the script to continue going down the list of p, regardless of non 0 returns, until each device in the list p has been touched.
My question: how can I make my while loop continue on regardless of non 0 returns.
#!/bin/bash
if [ -z "$1" ]
then
echo "Usage: "devices.txt""
exit 1
fi
FILENAME=$1
RESULTFILE="/home/user/ssim-results/RduLabTestResults"
date >> $RESULTFILE
while read p; do
echo "TESTING $p:"
LOGFILE="/home/user/ssim-results/RduLabTestLog_${p}.log"
SUMMARYFILE="/home/user/ssim-results/RduLabTestLog_${p}.summary"
#echo "STEP1: imagedeploy -d $p --latest-release4"
echo "STEP1: imagedeploy -d $p --latest-release4"
#imagedeploy -d $p --latest-release4
if [ $? -eq 0 ] #imagedeploy pass/failure condition
then
echo "STEP2: LLDP check"
#runtests.sh -l INFO --vx-img -i /home/frogs/vmlocker/cloud/vx/latest-vx-rel $TESTS_HOME/tests/platform/HydrationWiring.py -d $p -T $LOGFILE -r $SUMMARYFILE
runtests.sh -l INFO --vx-img -i $VXREL3 $TESTS_HOME/tests/platform/HydrationWiring.py -d $p -T $LOGFILE -r $SUMMARYFILE
echo "STEP3: checking result"
if grep --quiet success $SUMMARYFILE
then
echo "$p PASS" >> $RESULTFILE
else
echo "$p FAIL" >> $RESULTFILE
fi
else
echo "imagedeploy failed"
fi
done <$FILENAME
ImageDeploy is commented out because imagedeploy works as intended. The issue is in "step 2". The runtest.sh hydrationwiring
output:
FAILED (errors=1)
STEP3: checking result
It only tested the first device on my list because it failed, I would like the output to be something like this:
FAILED (errors=1)
STEP3: checking result
next device...
PASS
STEP3: checking result
next device...
FAILED (error=1)
STEP3: checking result
next device...
Passed
STEP3: checking result
etc

How to use terminal input as Python argument?

I am writing a Python script that is started by a .sh file and accepts 2-3 parameters. I have written what I want in Java, but I'm not sure how to put in bash.
Scanner i = new Scanner(System.in);
String f, f1, f2;
System.out.print("Enter type: ");
f = i.next();
if (f.equals("a")){
System.out.print("Enter var1");
f1 = i.next();
// run "python script.py a [f1]"
}
else if (f.equals("b")){
System.out.print("Enter var1");
f1 = i.next();
System.out.print("Enter var2");
f2 = i.next();
// run "python script.py b [f1] [f2]"
}
This is what I have so far:
a="e"
b="test.txt"
c=""
python main.py "$a" "$b" "$c"
I've looked at How to concatenate string variables in Bash, but I'm not sure how to put it in a conditional statement.
How do I put the read-ins in conditional statements in bash?
Here's a starter Bash script:
echo "Enter type"
read f
if [ "$f" = "a" ]; then
echo "Enter var1"
read f1
if [ -z "$f1" ]; then
# -z means "variable is empty", i.e. user only pressed Enter
python script.py "$f"
else
python script.py "$f" "$f1"
fi
fi

Converting a kshell script to python

Can anyone guide me? I'm trying to migrate a kshell script to python.
If anyone could guide me on how to proceed on this task. Do I really need the function? I'm trying to make more concise easy to read. Thank you.
here is the code:
#!/bin/ksh
DB="BATCH_JOB_STAT"
LINE=$DB
export $DB
NoFile()
{
# no file
COLOR="clear"
LINE=$DB" NO BATCH_JOB ERROR FLAG FOUND"
echo $LINE
$BB $BBDISP "status ${MACHINE}.BATCH_JOB_STAT $COLOR `date` $LINE"
exit 1
}
MultiFile()
{
fail_flag=0
# Check more than One file
files=$(ls /opt/rh/flag/*)
for file in $files
do
if [ -f $file ] ; then
## echo "# Error. Flag File found: $file"
fail_flag=1
fi
done
## echo "-- Fail flag is : $fail_flag"
if [ $fail_flag -eq 0 ]; then
# no FAIL status means GOOD
COLOR="green"
LINE=$DB" OK"
echo $LINE
else
COLOR="red"
LINE=$DB" BATCH_JOB ERROR FLAG FILE FOUND. <P> -- $file -- </P> <P> Support <A HREF=http://johndoe/support.htm> Tech </A>"
echo $LINE
fi
$BB $BBDISP "status ${MACHINE}.BATCH_JOB_STAT $COLOR `date` $LINE"
}
# MAIN
file_count=$(ls -l /opt/rh/flag 2>/dev/null |grep -v total |wc -l)
case "$file_count" in
0) NoFile ;;
*) MultiFile ;;
esac
exit 0
I suggest you to see shutil for high-level operations on files in Python. And of course, sys and os (which are used by the first).

how to import python variable to bash

I have two scripts:
Python:
if canceled==True:
os.environ["c"] = "0"
if canceled==False:
os.environ["c"] = "1"
Bash:
kill_jobs()
{
pkill -TERM -P "$BASHPID"
echo $c
if [ $c == "0" ]
then
echo -e "OPERATIONS CANCELED"
elif [ $c == "1" ]
then
echo -e "OPERATIONS FINISHED"
fi
}
trap kill_jobs EXIT
How can I do to pass a python variable to bash script ?
(My level in bash is near to 0 ...)
Thanks
Edit: Now I have this error: (in french)
[: == : opérateur unaire attendu
Or you can try:
os.environ["c"] = "value"
You can set it this way, I guess
Refer
The python script should end with:
print c
Then you use it in bash with:
c=$(python_script)

How to make a big shell script in a single line shell script in json document?

I am working on Python along with bash shell script. I need to execute shell script from the Python script. I am successfully able to do that.. I need to have a shell script in a single line in a JSON String..
Below is an example which is working fine for a simple shell script which I have made it in a JSON document...
import os
import json
import subprocess
jsonData = '{"pp": [0,3,5,7,9], "sp": [1,2,4,6,8]}'
jj = json.loads(jsonData)
os.putenv( 'jj3', ' '.join( str(v) for v in jj['pp'] ) )
os.putenv( 'jj4', ' '.join( str(v) for v in jj['sp'] ) )
jsonStr = '{"script":"#!/bin/bash \\n echo Hello World \\n "}'
j = json.loads(jsonStr)
shell_script = j['script']
print "start"
proc = subprocess.Popen(shell_script, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
(stdout, stderr) = proc.communicate()
if proc.returncode != 0:
print "Shell script gave some error"
print stdout
else:
print "end"
print stdout
Now I have a below shell script which I need to represent it in a single line in a JSON document as I have done for above Hello World use case..
#!/bin/bash
set -e
readonly PRIMARY=/tech01/primary
readonly SECONDARY=/tech02/secondary
readonly LOCATION=(machineA machineB)
readonly MAPPED_LOCATION=/bat/data/snapshot
HOSTNAME=$hostname
dir1=$(ssh -o "StrictHostKeyChecking no" david#${LOCATION[0]} ls -dt1 "$MAPPED_LOCATION"/[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9] | head -n1)
dir2=$(ssh -o "StrictHostKeyChecking no" david#${LOCATION[1]} ls -dt1 "$MAPPED_LOCATION"/[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9] | head -n1)
echo $dir1
echo $dir2
length1=$(ssh -o "StrictHostKeyChecking no" david#${LOCATION[0]} "ls '$dir1' | wc -l")
length2=$(ssh -o "StrictHostKeyChecking no" david#${LOCATION[1]} "ls '$dir2' | wc -l")
echo $length1
echo $length2
if [ "$dir1" = "$dir2" ] && [ "$length1" -gt 0 ] && [ "$length2" -gt 0 ]
then
rm -rf $PRIMARY/*
rm -rf $SECONDARY/*
for el in $primary_partition
do
scp david#${LOCATION[0]}:$dir1/weekly_8880_"$el"_5.data $PRIMARY/. || scp david#${LOCATION[1]}:$dir2/weekly_8880_"$el"_5.data $PRIMARY/.
done
fi
I have made the above shell script in a single line JSON document like this but this doesn't work and I always get an error
jsonStr = '{"script":"#!/bin/bash \n set -e \n readonly PRIMARY=/tech01/primary \n readonly SECONDARY=/tech02/secondary \n readonly LOCATION=(machineA machineB) \n readonly MAPPED_LOCATION=/bat/data/snapshot \n HOSTNAME=$hostname \n dir1=$(ssh -o \"StrictHostKeyChecking no\" david#${LOCATION[0]} ls -dt1 \"$MAPPED_LOCATION\"/[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9] | head -n1) \n dir2=$(ssh -o \"StrictHostKeyChecking no\" david#${LOCATION[1]} ls -dt1 \"$MAPPED_LOCATION\"/[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9] | head -n1) \n echo $dir1 \n echo $dir2 \n length1=$(ssh -o \"StrictHostKeyChecking no\" david#${LOCATION[0]} \"ls \'$dir1\' | wc -l\") \n length2=$(ssh -o \"StrictHostKeyChecking no\" david#${LOCATION[1]} \"ls \'$dir2\' | wc -l\") \n echo $length1 \n echo $length2 \n if [ \"$dir1\" = \"$dir2\" ] && [ \"$length1\" -gt 0 ] && [ \"$length2\" -gt 0 ] \n then \n rm -rf $PRIMARY/* \n rm -rf $SECONDARY/* \n for el in $primary_partition \n do \n scp david#${LOCATION[0]}:$dir1/t1_weekly_1680_\"$el\"_200003_5.data $PRIMARY/. || scp david#${LOCATION[1]}:$dir2/t1_weekly_1680_\"$el\"_200003_5.data $PRIMARY/. \n done \n fi"}'
This is the error I am getting -
ValueError: Invalid control character
Can anyone help me what wroing I am doing? And what's the right way to make above shell script in a Single line JSON document?
UPDATE:-
There is another twist into this which I thought its worth mentioning..
I need to store this single line shell script data in a Zookeeper node. So for Hello World shell script example case, I am storing by using the following code. I am using Curator library to write into Zookeeper.
client.create().creatingParentsIfNeeded().forPath("/be/wf/error1/v1/step1", "{\"description\":\"Hello World 1.\", \"script\":\"#!/bin/bash \\n set -e \\n echo Hello World 1 \\n\"}".getBytes());
And then I have my Python program to read the Zookeeper node data and then execute the shell script by extracting from the script tag..
Now I tried representing the same script as mentioned in the answer, in the above format, and my Eclipse started giving compilation errors on the string. So how do I represent the shell script as given in the answer in the above..
I guess I really need a JSON so that I can store it properly in Zookeeper node and then my Python program can read the same JSON data from the node and execute the shell script from the script tag.
First, consider whether you really need JSON. In your example code, you create a JSON string and then immediately decode it into a Python dict. Would it be simpler to just use a dict directly?
The problem with your current string is that you're not escaping your quotation marks properly. To avoid confusing multi-level escaping, use a triple-quoted string to represent the shell script and json.dumps to convert a dict into a JSON string:
import json
jsonstr = json.dumps({"script": """\
#!/bin/bash
set -e
readonly PRIMARY=/tech01/primary
readonly SECONDARY=/tech02/secondary
readonly LOCATION=(machineA machineB)
readonly MAPPED_LOCATION=/bat/data/snapshot
HOSTNAME=$hostname
dir1=$(ssh -o "StrictHostKeyChecking no" david#${LOCATION[0]} ls -dt1 "$MAPPED_LOCATION"/[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9] | head -n1)
dir2=$(ssh -o "StrictHostKeyChecking no" david#${LOCATION[1]} ls -dt1 "$MAPPED_LOCATION"/[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9] | head -n1)
echo $dir1
echo $dir2
length1=$(ssh -o "StrictHostKeyChecking no" david#${LOCATION[0]} "ls '$dir1' | wc -l")
length2=$(ssh -o "StrictHostKeyChecking no" david#${LOCATION[1]} "ls '$dir2' | wc -l")
echo $length1
echo $length2
if [ "$dir1" = "$dir2" ] && [ "$length1" -gt 0 ] && [ "$length2" -gt 0 ]
then
rm -rf $PRIMARY/*
rm -rf $SECONDARY/*
for el in $primary_partition
do
scp david#${LOCATION[0]}:$dir1/weekly_8880_"$el"_5.data $PRIMARY/. || scp david#${LOCATION[1]}:$dir2/weekly_8880_"$el"_5.data $PRIMARY/.
done
fi"""})
Alternatively, you could put the shell script in its own file and open the file to read the string from it.

Categories

Resources