This same problem is better formulated in a question posted to the Unix & Linux StackExchange community.
I am programming a script which opens on a key press, open a new terminal (gnome-terminal), runs scrot (screenshot tool), saves the picture with random name to a directory, uploads it to pomf.cat and copies the link to the clipboard.
This works fine. What im trying to do now is, when uploading is done, close the terminal.
My script works like this:
Shortcut (PrtScr) -> gnome-terminal -e "python path/to/script.py" -> Start Scrot -> Save File (and remember path to file) -> bash script2.sh path/to/picture -> Upload to pomf.cat -> Get the link -> Put into clipboard via "xclip -selection clipboard"
Since i want to close the Terminal after putting the String into Clipboard, i added this:
eval $(printf $link | xclip -selection clipboard && sleep 1 && pkill terminal)
The problem with this is, nothing gets copied into clipboard and the terminal closes.
However, without "&& sleep 1 && pkill terminal" the link gets copied but the terminal stays open.
Thanks in advance.
//EDIT
First Script (for running scrot)
#!/usr/bin/env python
import os
import uuid
import time
def rstring(string_length=10):
random = str(uuid.uuid4())
random = random.upper()
random = random.replace("-","")
return random[0:string_length]
randomString = rstring(16)
os.system("scrot -s -q 100 /home/timon/screenshots/" + randomString + ".jpg")
while True:
processRead = os.popen("ps aux | grep \"scrot -s\" | cat").read()
if "scrot -s" not in processRead:
time.sleep(1)
else:
break
system.sleep(3)
os.system("/home/timon/.screenshot_stuff/./screen.sh /home/timon/screenshots/" + randomString + ".jpg")
Second Script (for uploading the screenshot)
#!/usr/bin/env bash
dest_url='https://cuntflaps.me/upload.php'
return_url='https://a.cuntflaps.me'
if [[ -n "${1}" ]]; then
file="${1}"
if [ -f "${file}" ]; then
printf "Uploading ${file}..."
my_output=$(curl --silent -sf -F files[]="#${file}" "${dest_url}")
n=0 # Multipe tries
while [[ $n -le 3 ]]; do
printf "try #${n}...\n"
if [[ true ]]; then
return_file=$(echo "$my_output" | grep "url" | sed 's/\,//g' | sed 's/\\//g' | sed 's/\"//g' | sed 's/\url://g' | tr -d ' ')
printf 'done.\n'
break
else
printf 'failed.\n'
((n = n +1))
fi
done
printf "$return_file" | xclip -selection clipboard && pkill terminal
else
printf 'Error! File does not exist!\n'
exit 1
fi
else
printf 'Error! You must supply a filename to upload!\n'
exit 1
fi
So in the end i came up with my own solution.
The problem seemed to be xclip itself.
Now i use "xsel --clipboard --input", which seems to work, even after exiting directly.
Related
I established a connection with a BLE device using gatttool. First I connected to the device with sudo gatttool -t random -b FF:3C:8F:22:C9:C8 -I and connect. After that I read the value of specific characteristic with char-read-uuid 2d30c082-f39f-4ce6-923f-3484ea480596.
What I want to do is to automate the whole process and put the latter command (querying for value) in the loop, ideally saving each value (appending) to a text file. I tried something like
sudo gatttool -t random -b FF:3C:8F:22:C9:C8 -I <<EOF
connect
while[ 1 ]; do
char-read-uuid 2d30c082-f39f-4ce6-923f-3484ea480596 > output.txt
done
exit 1
EOF
but it does not help, since I am not even able to connect to the device (ideally there should be some delay between the first and the second command). Also after connecting, an interactive mode is enabled and the shell commands do not work there. I'd appreciate any clues on how to tackle this issue.
If gattool writes prompts to stdout (and doesn't suppress them given non-TTY file descriptors), consider something like:
#!/usr/bin/env bash
case $BASH_VERSION in ''|[123].*|4.0.*) echo "ERROR: bash 4.1 or newer required" >&2; exit 1;; esac
exec {output_fd}>output.txt
prompt_re='[>] '
capture_re='^handle:.*value:.*$'
wait_for_prompt() {
IFS= read -r line || return
while ! [[ $line =~ $prompt_re ]]; do
[[ $line =~ $capture_re ]] && printf '%s\n' "$line" >&$output_fd
IFS= read -r line || return
done
}
wait_for_prompt
echo connect
while wait_for_prompt; do
echo "char-read-uuid 2d30c082-f39f-4ce6-923f-3484ea480596"
done
...saved as yourscript, and invoked using socat as:
socat 'SYSTEM:sudo gatttool -t random -b FF:3C:8F:22:C9:C8 -I 2>&1' 'EXEC:./yourscript'
(assuming that sudo is configured to work without a TTY; otherwise, you might move it to be sudo socat).
Indeed, pexpect works fine here. You can find my solution below. The code reads the value of the specific UUID, which contains IMU readings (floats).
import pexpect
import struct
import time
import sys
IMU_MAC_ADDRESS = "FF:3C:8F:22:C9:C8"
UUID_DATA = "2d30c082-f39f-4ce6-923f-3484ea480596"
if __name__ == '__main__':
gatt = pexpect.spawn("gatttool -t random -b " + IMU_MAC_ADDRESS + " -I")
gatt.sendline("connect")
gatt.expect("Connection successful")
while(True):
gatt.sendline("char-read-uuid " + UUID_DATA)
gatt.expect("handle: 0x0011 value: ")
gatt.expect(" \r\n")
data = (gatt.before).decode('UTF-8').replace(" ", "").decode('hex')
print(struct.unpack('f', data)[0]
I'd like to use notify-send from within a bash script that is running in the background to inform the user about the progress of the script. More specifically this is a script that automagically runs when a USB flash drive is inserted and runs a scan with ClamAV.
Specifically at line 30 and line 66. So far, I'm not having any luck. Can someone give me some advice/help? Thanks.
#!/bin/bash
#doOnUSBinsert_0.2.sh
#Author : Totti
# Make it executable by running 'sudo chmod x doOnUSBinsert_0.2.sh'
if ! [ -f /etc/udev/rules.d/80-doOnUSBinsert.rules ]
then # rule not added
cp "$0" /usr/bin/doOnUSBinsert
chmod u x /usr/bin/doOnUSBinsert
# echo 'SUBSYSTEM=="usb", ACTION=="add", RUN ="/path/to/script.sh"' | sudo tee /etc/udev/rules.d/80-clamscan.rules
echo 'SUBSYSTEM=="usb", ACTION=="add", RUN ="/usr/bin/doOnUSBinsert & "' | tee /etc/udev/rules.d/80-doOnUSBinsert.rules
if [ $? -eq 0 ]
then
echo 'Rule Successfully added. See file "/usr/bin/doOnUSBinsert" if you wish to edit the command'
exit 0
else
echo 'ERROR while adding rule'
exit 1
fi
fi
lfile="/tmp/doOnUSBinsert.log" # udev
lfile2="/tmp/clamscanFromUdev.log" # clamscan
lfile3="/tmp/doOnUSBinsert_mount.log" # mount
notify-send "USB SCAN ON INSERT" "Currently scanning with ClamAV"
main ()
{
sleep 12 # let the partitions to mount
#cat /proc/$$/environ | tr '�' 'n' >> /tmp/udevEnvirn.txt
echo "found $ID_SERIAL" >> "$lfile"
cat /etc/mtab | grep "^$part_c" >> "$lfile.3"
if [ "$ID_SERIAL"x = 'x' ]
then
echo "Exiting on empty ID_SERIAL" >> "$lfile"
exit 1
fi
#Eg: ID_SERIAL --> /dev/disk/by-id/usb-sandisk....42343254343543
#i=0
echo 'searching partitions' >> "$lfile"
for partitionPath in $( find /dev/disk/by-id/ -name "*$ID_SERIAL*part*" )
do
echo "current partition = $partitionPath" >> "$lfile"
# part[i ]="$( readlink -f "$partition" )" # Eg Output: /dev/sdb1 , /dev/sdb2
part_c="$( readlink -f $partitionPath )"
mpoint="$( cat /etc/mtab | grep "^$part_c" | awk '{print $2}' )"
echo "partitionPath= $partitionPath, part = $part_c, mountpoint= $mpoint" >> "$lfile"
echo "Scaning --> $mpoint" >> "$lfile.2"
############################################
clamscan -r --bell "$mpoint"/* >> "$lfile.2"
#############################################
done
}
notify-send "USB SCAN ON INSERT" "Finished scanning with ClamAV"
main &
echo ______________________________________ >> "$lfile"
exit 0
I'm pretty new to the linux world, but while looking for a solution for a similar project I found THIS
Tip: An overview on the available icons can be found here. To send
desktop notification from a background script running as root (replace
X_user and X_userid with the user and userid running X respectively):
sudo -u X_user DISPLAY=:0 DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/X_userid/bus notify-send 'Hello world!' 'This is an example notification.'
Hope this will help others.
Depending on how you are running the script it may not have access to the display variable. Try running export DISPLAY=:0.0 prior to the command.
If you are running the script as a different user, ie root, then you may also need to run it as su - <logged in user> -c notify-send ... (I usually don't need to do this, but I remember having to at one point - but I cant recall which distro or version I was on at the time.)
This issue is currently driving me nuts.
I setup a crontab with sudo crontab -e
The contents are 1 * * * * /home/bolte/bin/touchtest.sh
The contents of that file are:
#!/bin/bash
touch /home/bolte/bin/test.log
It creates the file. But the below script will not run.
#!/bin/bash
# CHANGE THESE
auth_email="11111111#live.co.uk"
auth_key="11111111111111111" # found in cloudflare
account settings
zone_name="11111.io"
record_name="11111.bolte.io"
# MAYBE CHANGE THESE
ip=$(curl -s http://ipv4.icanhazip.com)
ip_file="/home/bolte/ip.txt"
id_file="/home/bolte/cloudflare.ids"
log_file="/home/bolte/cloudflare.log"
# LOGGER
log() {
if [ "$1" ]; then
echo -e "[$(date)] - $1" >> $log_file
fi
}
# SCRIPT START
log "Check Initiated"
if [ -f $ip_file ]; then
old_ip=$(cat $ip_file)
if [ $ip == $old_ip ]; then
echo "IP has not changed."
exit 0
fi
fi
if [ -f $id_file ] && [ $(wc -l $id_file | cut -d " " -f 1) == 2 ]; then
zone_identifier=$(head -1 $id_file)
record_identifier=$(tail -1 $id_file)
else
zone_identifier=$(curl -s -X GET "https://api.cloudflare.com/client/v4/zones?name=$zone_name" -H "X-Auth-E$
record_identifier=$(curl -s -X GET "https://api.cloudflare.com/client/v4/zones/$zone_identifier/dns_record$
echo "$zone_identifier" > $id_file
echo "$record_identifier" >> $id_file
fi
update=$(curl -s -X PUT "https://api.cloudflare.com/client/v4/zones/$zone_identifier/dns_records/$record_ident$
[ Read 55 lines (Warning: No write permission) ]
^G Get Help ^O Write Out ^W Where Is ^K Cut Text ^J Justify ^C Cur Pos ^Y Prev Page
^X Exit ^R Read File ^\ Replace ^U Uncut Text ^T To Linter ^_ Go To Line ^V Next Page
I've been trying to troubleshoot why this code will not run every minute, there doesn't seem to be any output in the same folder as the script, which is located at /home/bolte/cloudflare-update-record.sh
Ok so the answer to this was, I was editing crontab with sudo, and the files were located in my users home folder. This is why they weren't working. Resolved my own issue.
If you have this issue just use $ crontab -e rather than sudo crontab -e, and specify full paths for your file outputs, unless you are putting the proper path variables in your script.
I'm working on a bash script, opening a yad window and keeping it opened until internet connection is present and then closing it.
It looks as follow:
#!/bin/bash
yad_wind1_id=""
yad_wind1_id_txt_str=""
NET_STATE=0
function test_net_connection()
{
(ping -c 1 www.google.com &>/dev/null)
XCODE=$?
if [ $XCODE == 0 ]; then
NET_STATE=1
else
NET_STATE=0
fi
}
function kill_yad_proc()
{
kill_proc=$(ps aux | grep "$1" | grep -v "grep $1" | \
awk '{print $2}' | sed 's:^:kill :')
eval $kill_proc
}
function yad_proc_id_string()
{
yad_win_id=`echo $(date +%F-%H-%M-%6N) | \
sed 's/-/_/g' | sed 's/^/text=/'`
yad_win_id_txt_str="--""$yad_win_id"
}
yad_proc_id_string
# ...and here starts my problem...
while [[ $NET_STATE == 0 ]]; do
test_net_connection
if [[ $XCODE == 0 ]]; then
NET_STATE=1
kill_yad_proc "$yad_win_id"
break
exit
else
NET_STATE=0
continue
fi
done | `yad --fixed --skip-taskbar --undecorated \
"$yad_win_id_txt_str" \
--text="Waiting for internet connection..." \
--button='Quit:bash -c "kill -USR1 $YAD_PID"' \
--image=disconnected.png`
In this version script works just partly: when internet is off, yad window appears and disappears when internet is on (ping returns 0). Unfortunately, when I press [Quit] button or [escape] (however I'd like to keep this option), it doesn't work as I'd like it to.
What should I add/change? Where the mistake is done?
"when I press [Quit] button or [escape] (however I'd like to keep this
option)"
I guess yad is outside loop and this is your problem.
TIP.
- I do not see sense to check the connection with ping.
But maybe you need and maybe this is best way.
Best should be find file inside system for internet conection status and use inotifywait
however inotify sometimes is also buggy so you should be carefully.
- You can add own icon tray with yad,
but you need create two functions with yad with other icons and title.
When inetrnet status will change, you can kill first yad window and open next window.
This can be in "while" loop when status internet is tested.
I'm not used to writing code in bash but I'm self teaching myself. I'm trying to create a script that will query info from the process list. I've done that but I want to take it further and make it so:
The script runs with one set of commands if A OS is present.
The script runs with a different set of commands if B OS is present.
Here's what I have so far. It works on my Centos distro but won't work on my Ubuntu. Any help is greatly appreciated.
#!/bin/bash
pid=$(ps -eo pmem,pid | sort -nr -k 1 | cut -d " " -f 2 | head -1)
howmany=$(lsof -l -n -p $pid | wc -l)
nameofprocess=$(ps -eo pmem,fname | sort -nr -k 1 | cut -d " " -f 2 | head -1)
percent=$(ps -eo pmem,pid,fname | sort -k 1 -nr | head -1 | cut -d " " -f 1)
lsof -l -n -p $pid > ~/`date "+%Y-%m-%d-%H%M"`.process.log 2>&1
echo " "
echo "$nameofprocess has $howmany files open, and is using $percent"%" of memory."
echo "-----------------------------------"
echo "A log has been created in your home directory"
echo "-----------------------------------"
echo " "
echo ""$USER", do you want to terminate? (y/n)"
read yn
case $yn in
[yY] | [yY][Ee][Ss] )
kill -15 $pid
;;
[nN] | [n|N][O|o] )
echo "Not killing. Powering down."
echo "......."
sleep 2
;;
*) echo "Does not compute"
;;
esac
Here's my version of your script. It works with Ubuntu and Debian. It's probably safer than yours in some regards (I clearly had a bug in yours when a process takes more than 10% of memory, due to your awkward cut). Moreover, your ps are not "atomic", so things can change between different calls of ps.
#!/bin/bash
read percent pid nameofprocess < <(ps -eo pmem,pid,fname --sort=-pmem h)
mapfile -t openfiles < <(lsof -l -n -p $pid)
howmany=${#openfiles[#]}
printf '%s\n' "${openfiles[#]}" > ~/$(date "+%Y-%m-%d-%H%M.process.log")
cat <<EOF
$nameofprocess has $howmany files open, and is using $percent% of memory.
-----------------------------------
A log has been created in your home directory
-----------------------------------
EOF
read -p "$USER, do you want to terminate? (y/n) "
case $REPLY in
[yY] | [yY][Ee][Ss] )
kill -15 $pid
;;
[nN] | [n|N][O|o] )
echo "Not killing. Powering down."
echo "......."
sleep 2
;;
*) echo "Does not compute"
;;
esac
First, check that your version of ps has the --sort flag and the h option:
--sort=-pmem tells ps to sort wrt decreasing pmem
h tells ps to not show any header
All this is given to the read bash builtin, which reads space-separated fields, here the fields pmem, pid, fname and puts these values in the corresponding variables percent, pid and nameofprocess.
The mapfile command reads standard input (here the output of the lsof command) and puts each line in an array field. The size of this array is computed by the line howmany=${#openfiles[#]}. The output of lsof, as stored in the array openfiles is output to the corresponing file.
Then, instead of the many echos, we use a cat <<EOF, and then the read is use with the -p (prompt) option.
I don't know if this really answers your question, but at least, you have a well-written bash script, with less multiple useless command calls (until your case statement, you called 16 processes, I only called 4). Moreover, after the first ps call, things can change in your script (even though it's very unlikely to happen), not in mine.
You might also like the following which doesn't put the output of lsof in an array, but uses an extra wc command:
#!/bin/bash
read percent pid nameofprocess < <(ps -eo pmem,pid,fname --sort=-pmem h)
logfilename="~/$(date "+%Y-%m-%d-%H%M.process.log")
lsof -l -n -p $pid > "$logfilename"
howmany=$(wc -l < "$logfilename")
cat <<EOF
$nameofprocess has $howmany files open, and is using $percent% of memory.
-----------------------------------
A log has been created in your home directory ($logfilename)
-----------------------------------
EOF
read -p "$USER, do you want to terminate? (y/n) "
case $REPLY in
[yY] | [yY][Ee][Ss] )
kill -15 $pid
;;
[nN] | [n|N][O|o] )
echo "Not killing. Powering down."
echo "......."
sleep 2
;;
*) echo "Does not compute"
;;
esac
You could achieve this for example by (update)
#!/bin/bash
# place distribution independent code here
# dist=$(lsb_release -is)
if [[ -f /etc/redheat-release ]];
then # this is a RedHead based distribution like centos, fedora, ...
dist="redhead"
elif [[ -f /etc/issue.net ]];
then
# dist=$(cat /etc/issue.net | cut -d' ' -f1) # debian, ubuntu, ...
dist="ubuntu"
else
dist="unknown"
fi
if [[ $dist == "ubuntu" ]];
then
# use your ubuntu command set
elif [[ $dist == "redhead" ]];
then
# use your centos command set
else
# do some magic here
fi
# place distribution independent code here