Bash script not working when run outside terminal - bash

This script does not function properly when launched graphically (by double clicking script icon and selecting run), however, runs just fine if called from the terminal; will not save a file or load contents from an existing file. Please help! Thank you.
#!/bin/bash
# This script provides a simple and secure messaging system for users not
# familiar with gpg or using the terminal. The idea is to keep sensitive
# plaintext files off one's computer.
zenity --question --text="Select operation:" --ok-label="Compose" --cancel-label="Read"
if [[ $? == 0 ]]; then
usr=$(zenity --entry --text="Sender Key ID:")
rec=$(zenity --entry --text="Recipient Key ID:")
pwd=$(zenity --password)
outfile=$(zenity --file-selection --save --confirm-overwrite)
zenity --text-info --editable | gpg -aseu $usr -r $rec --passphrase $pwd --cipher-algo AES256 -o $outfile
else
infile=$(zenity --file-selection)
pwd=$(zenity --password)
gpg -d --passphrase $pwd $infile | zenity --text-info --height=600 --width=800
fi

A probable cause for the error is that you have different environments when executing via an interactive shell (thus sourcing your .bashrc) and double-clicking (non-interactive, and not sourcing .bashrc
You can compare the environments by doing an env > from_terminal vs. env > double_click and then using diff or something similar.
You could also (after doing the above) source from_terminal in your script to see if it works with the terminal environment. As stated in one of the comments, set -vx is your friend.

Related

bash script to log as another user and keep the terminal open

I have set up a http server at localhost, with several sites. I would like to connect to each site root folder, at the same way I used to at a remote server via ssh. So, I tried to create a bash script, intended to log as user "http", giving the site root folder as argument and change the $HOME to the site root folder:
#!/bin/bash
echo "Connecting to $1 as http...";
read -p "Contraseña: " -s pass;
su - http << EOSU >/dev/null 2>&1
$pass
export HOME="/srv/http/$1";
echo $HOME;
source .bash_profile;
exec $SHELL;
EOFSU
It does not work, basically because of:
echo $HOME keeps giving out the home folder of the user launching the script.
when the script reaches the end, it ends (obvious), but I would like that it stays open, so I could have a terminal session for user "http" and go on typing commands.
In other words, I am looking for a script that saves me 3 commands:
# su - http
# cd <site_root_folder>
# export HOME=<site_root_folder>
Edit:
Someone suggested the following:
#!/bin/bash
init_commands=(
"export HOME=/srv/http/$(printf '%q' "$1")"
'cd $HOME'
'. .bash_profile'
)
su http -- --init-file <(printf '%s\n' "${init_commands[#]}")
I am sorry but their post is gone... In any case, this give me out bash: /dev/fd/63: permission denied. I am not so skillful to understand the commands above and try to sort it out. Can someone help me?
Thanks.
Possible solution:
I have been playing around, based on what was posted and some googling, and finally I got it :-)
trap 'rm -f "$TMP"' EXIT
TMP=$(mktemp) || exit 1
chmod a+r $TMP
cat >$TMP <<EOF
export HOME=/srv/http/$(printf '%q' "$1")
cd \$HOME
. .bash_profile
EOF
su http -- --init-file $TMP
I admit it is not a nice code, because of:
the temporary file is created by the user executing the script and later I have to chmod a+r so user "http" can access... not so good.
I am sure this can be done on the fly, without creating a tmp file.
If some can improve it, it will be welcome; although in any case, it works!
Your main problem is that the $HOME is evaluated as when the user run the script, meaning that it will get his evaluation of $HOME instead of evaluating it as the given user.
You can evaluate the $HOME as the given user (using the eval command) but I wont recommend it, it is generally bad practice to use this kind of evaluation, especially when talking about security.
I can recommend you to get the specific user home directory with standard linux tools like passwd
Example of the behavior you are seeing:
# expected output is /home/eliott
$ sudo -u eliott echo $HOME
/root
Working it around with passwd:
$ sudo -u eliott echo $(getent passwd eliott | cut -d: -f6)
/home/eliott

Adding printers by shell script; works in terminal but not as .command

I am trying to provide a clickable .command to set up printers in Macs for my workplace. I thought since it is something I do very frequently, I can write a shellscript for each printer and save it on a shared server. Then, when I need to add a printer for someone, I can just find the shell script on the server and execute it. My current command works in terminal, but once executed as a .command, it comes up with the errors.
This is my script:
#!/bin/sh
lpadmin -p ‘PRINTERNAME’ -D PRINTER\ NAME -L ‘OFFICE’ -v lpd://xx.xx.xx.xx -P /Library/Printers/PPDs/Contents/Resources/Xerox\ WorkCentre\ 7855.gz -o printer-is-shared=false -E​
I get this error after running the script:
lpadmin: Unknown option “?”.
I find this strange, because there is no "?" in the script.
I have a idea, why not try it like this ? there are huge differences between sh shells, so let me know if it rocks, I have more ideas.
#!/bin/sh
PPD="PRINTERNAME"
INFO="PRINTER\ NAME"
LOC="OFFICE"
URI="lpd://xx.xx.xx.xx"
OP ="printer-is-shared=false"
# This parameter P is new to me. Is it the paper-name ?
P="/Library/Printers/PPDs/Contents/Resources/Xerox\ WorkCentre\ 7855.gz"
lpadmin -p "$PPD" -D "$INFO" -L "$LOC" -v "$URI" -P "$P" -o "$OP" -E;

Rofi custom script on combi mode

I made a simple custom script to quick open a project on vscode thanks to ghq:
selection=$(ghq list | rofi -dmenu -p "Project" -no-custom)
[[ ! -z "${selection}" ]] && code ${HOME}/p/${selection}
exit 0
I bound it on i3 config:
bindsym $mod+d exec --no-startup-id rofi -show combi
bindsym $mod+p exec --no-startup-id ~/.config/rofi/project.sh
It works like a charm. Howeverm I want to make it part of the combi mode in order to have only one shortcut.
How can I achieve this?
If this is not possible with rofi, does a similar tool permit that?
It is possible to do by adding a script to your rofi config in ~/.config/rofi/config.rasi:
configuration {
combi-modi: "window,drun,ssh,Project:~/.config/rofi/project.sh";
modi: "combi";
}
Then you need to modify your script, so it will return a list of projects when no arguments are given and open a project when the script is launched with a project name as an argument:
#!/usr/bin/env sh
# List projects if no arguments given
if [ -z "$1" ]; then
ghq list
else
code "$HOME/p/$1"
fi
Now, rofi -show combi should open with a default combi mode+project launcher.
By the way, I am not sure if the exit 0 at the end of the script is needed. It makes the script always return successful status, no matter the exit status of used commands. See the answer here.
In my case, I was trying a simple file finder script for rofi
At first my attempt was:
fd -H . ~ | rofi -dmenu | xargs xdg-open > /dev/null 2>&1 &
Calling the script from the command line works like a charm, but when I tried this inside rofi, didn't work. Of course I can't call rofi indide rofi
Following the idea here, given by Cezary,I got to this:
#!/bin/bash
if [[ -z "$1" ]]; then
fd -H . ~
else
xdg-open "$1" > /dev/null 2>&1 &
fi
Turns out, de > /dev/null 2>&1 & was important, so it wouldn't freeze the whole thing. Maybe only the "&" in the end is important, so the process goes to the background? The rest, as I understand, just throws away any output or errors.
In my "config.rasi" from rofi, I have the line
modi: "drun,Finder:/path/to/script";
since I want it as a second mode, instead of a combi. Of course I made it executable with chmod +x.

Automating Passphrase in a Bash Script (steghide, gpg, etc.)

I've been working on a series of bash scripts and I need to automate password entry for batch processing of files and actions.
This isn't for just one program, for example, sometimes it needs to be done for GPG, other times, steghide.
There is a specific reason this is being done and I understand the security elements behind it. This is considered and is negated by how the scripts are stored and working.
The passwords or passphrases are passed via command line arguments to the script and the password/phrase must be repeated many times programmatically.
Here is an example of what I am working with inside the script:
for f in $dir
do
steghide embed -cf $f -ef /path/to/secret.txt
done
This simply interactively asked this for every image however:
Enter Passphrase:
Re-enter Passphrase:
For every image in a directory, this password will be requested and so the password should be able to be stored in a variable and reused.
I have been working with steghide most recently but there will also be a need to automate passphrases with GPG at a later date, although there is no need for the methods to be the same.
man steghide:
-p, --passphrase
Use the string following this argument as the
passphrase. If your passphrase contains whitespace,
you have to enclose it in quotes, for example: -p
"a very long passphrase".
man gpg:
--passphrase string
Use string as the passphrase. This can only be used if only one
passphrase is supplied. Obviously, this is of very questionable
security on a multi-user system. Don't use this option if you can
avoid it.
It's untested publicly, rough around the edges, and can be improved... but here's a preview of some of my research scripts that haven't been merged into one of the GitHub projects I'm writing... definitely run shellcheck against the below script to catch any typos.
#/usr/bin/env bash
Var_stego_out_dir="${1}"
Var_stego_in_dir="${2}"
Var_stego_cover_dir="${3}"
Var_passphrase_file="${4}"
Var_passphrase="${5}"
Var_auto_pass_length="${6:-64}"
Func_build_array_of_paths(){
_dir="${1}"
_arr="${2}"
_file_extension_list="${3}"
if [ -d "${_dir}" ] && [ "${#${_arr}[#]}" = "0" ]; then
find "${_dir}" -xtype f | while read _path; do
case "${_path##*.}" in
${_file_extension_list//,/|})
declare -ag "${_arr}+=( ${_path} )"
;;
esac
done
fi
}
Func_enc_stego(){
_cover_file="${1}"
_enc_file="${2}"
_pass_file="${3}"
_output_file="${Var_stego_out_dir}/${_cover_file##*/}"
if [ -f "${_cover_file}" ] && [ -f "${_enc_file}" ]; then
_auto_passphrase="${Var_passphrase:-$(base64 /dev/random | tr -cd '[:print:]' head -c${Var_auto_pass_length})}"
if ! [ -f "${_output_file}" ]; then
steghide -p ${_auto_passphrase} -ef ${_enc_file} -cf ${_cover_file} -sf ${_output_file}
cat <<<"### ${_output_file} ### ${_auto_passphrase}" >> "${_pass_file}"
else
steghide -p ${_auto_passphrase} -ef ${_enc_file} -cf ${_cover_file} -sf ${_output_file}_$(date -u +%s)
cat <<<"### ${_output_file}_$(date -u +%s) ### ${_auto_passphrase}" >> "${_pass_file}"
fi
fi
}
Func_main(){
## Build array of file paths for cover file use
Func_build_array_of_paths "${Var_stego_cover_dir}" "Arr_cover_list" "au,AU,bmp,BMP,jpeg,JPEG,wav,WAV"
## Build array of file paths for embed file use
Func_build_array_of_paths "${Var_stego_in_dir}" "Arr_input_list" "gpg,GPG,txt,TXT"
let _arr_input_count=0
let _arr_cover_count=0
until [ "${_arr_input_count}" = "${#Arr_input_list}" ]; do
if [ -f "${Arr_cover_list[${_arr_cover_count}]}" ]; then
Func_enc_stego "${Arr_cover_list[${_arr_cover_count}]}" "${Arr_input_list[${_arr_input_count}]}" "${Var_passphrase_file}"
let _arr_cover_count++
let _arr_input_count++
elif [ -f "${Arr_cover_list[$((${_arr_cover_count}-1))]}" ]; then
Func_enc_stego "${Arr_cover_list[$((${_arr_cover_count}-1))]}" "${Arr_input_list[${_arr_input_count}]}" "${Var_passphrase_file}"
let _arr_input_count++
_arr_cover_count="$((${_arr_cover_count}-1))"
if
done
}
Func_main
Run above with the following portions filled-in
script.sh "/path/to/stego_out_dir" "/path/to/stego_in_dir" "/path/to/stego_cover_dir" "/path/to/passphrase_file"
## or define static passphrase
#script.sh "/path/to/stego_out_dir" "/path/to/stego_in_dir" "/path/to/stego_cover_dir" "/path/to/passphrase_file" "passphrase"
Note saving the passphrase and file in plain-text like the above does is very bad practice, and because the OP stated that they also where looking at GnuPG automation too, readers and the OP"s author should look-up Perinoid_Pipes; and for specifically the GnuPG_Gen_Key.sh script and functions starting with Func_dec_* within the Paranoid_Pipes.sh for working/tested examples of automation involving GnuPG passphrases; and for protecting the passphrases written by the above script look-up functions starting with Func_enc_* within the Paranoid_Pipes.sh script for how the mkfifo command and resulting named pipe is used to automate encryption of most data types. Hint the fourth example argument "/path/to/passphrase_file" would point to an encrypting named pipe made by the linked script to keep things a bit more secure ;-)

OSX bash script works but fails in crontab on SFTP

this topic has been discussed at length, however, I have a variant on the theme that I just cannot crack. Two days into this now and decided to ping the community. THx in advance for reading..
Exec. summary is I have a script in OS X that runs fine and executes without issue or error when done manually. When I put the script in the crontab to run daily it still runs but it doesnt run all of the commands (specifically SFTP).
I have read enough posts to go down the path of environment issues, so as you will see below, I hard referenced the location of the SFTP in the event of a PATH issue...
The only thing that I can think of is the IdentityFile. NOTE: I am putting this in the crontab for my user not root. So I understand that it should pickup on the id_dsa.pub that I have created (and that has already been shared with the server)..
I am not trying to do any funky expect commands to bypass the password, etc. I dont know why when run from the cron that it is skipping the SFTP line.
please see the code below.. and help is greatly appreciated.. thx
#!/bin/bash
export DATE=`date +%y%m%d%H%M%S`
export YYMMDD=`date +%y%m%d`
PDATE=$DATE
YDATE=$YYMMDD
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
FEED="~/Dropbox/"
USER="user"
HOST="host.domain.tld"
A="/tmp/5nPR45bH"
>${A}.file1${PDATE}
>${A}.file2${PDATE}
BYEbye ()
{
rm ${A}.file1${PDATE}
rm ${A}.file2${PDATE}
echo "Finished cleaning internal logs"
exit 0
}
echo "get -r *" >> ${A}.file1${PDATE}
echo "quit" >> ${A}.file1${PDATE}
eval mkdir ${FEED}${YDATE}
eval cd ${FEED}${YDATE}
eval /usr/bin/sftp -b ${A}.file1${PDATE} ${USER}#${HOST}
BYEbye
exit 0
Not an answer, just comments about your code.
The way to handle filenames with spaces is to quote the variable: "$var" -- eval is not the way to go. Get into the habit of quoting all variables unless you specifically want to use the side effects of not quoting.
you don't need to export your variables unless there's a command you call that expects to see them in the environment.
you don't need to call date twice because the YYMMDD value is a substring of the DATE: YYMMDD="${DATE:0:6}"
just a preference: I use $HOME over ~ in a script.
you never use the "file2" temp file -- why do you create it?
since your sftp batch file is pretty simple, you don't really need a file for it:
printf "%s\n" "get -r *" "quit" | sftp -b - "$USER#$HOST"
Here's a rewrite, shortened considerably:
#!/bin/bash
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
FEED_DIR="$HOME/Dropbox/$(date +%Y%m%d)"
USER="user"
HOST="host.domain.tld"
mkdir "$FEED_DIR" || { echo "could not mkdir $FEED_DIR"; exit 1; }
cd "$FEED_DIR"
{
echo "get -r *"
echo quit
} |
sftp -b - "${USER}#${HOST}"

Resources