0

I have a .sh script that runs changes to PostgreSQL DB, and provides a report of those changes. As an output from the script a report.csv file is produced. The server has multiple users that are only allowed to read the file. At the end of the script I want to zip and archive it (.csv and .zip files are both the purposed outcome). These directives require using sudo rights to run. My question is how to arrange the shell commands semantically correct so that I use sudo as less as possible?

I cannot run the whole script as sudo since it uses psql access and that would change the user running the db access to root.

#!/bin/bash
sudo chmod 440 /tmp/$REPORT_FILE

# Move to archive folder and rename
sudo mv /tmp/$REPORT_FILE/$ARCHIVE_DIR$/$REPORT_NAME

cd $ARHIVE_DIR
sudo zip ${REPORT_ZIP_NAME} {REPORT_NAME}
sudo chmod 440 ${REPORT_ZIP_NAME}
rm $REPORT_NAME
  • Your script does not contain any SQL operations, so I assume, that they are somewhere in between those lines, and you just don't show them. In this case, you have a mixture of sudo and normal commands, and in this case, I find it the clearest solution if you do an explicit sudo for each statement where it is needed. – user1934428 Mar 20 '23 at 12:20
  • Get rid of `sudo` altogether and use an appropriately populated group to restrict access to the files. – chepner Mar 20 '23 at 13:23

2 Answers2

2

For limiting the sudo calls to one you could create a temporary directory, do your stuff, and then move the files:

#!/bin/bash

REPORT_NAME=myReportName
REPORT_ZIP_NAME=something.zip
ARCHIVE_DIR=/some/path

tempdir=$(mktemp -d)
chmod 700 "$tempdir"

# ... "$REPORT_FILE" is created in "$tempdir" one way or another ...

pushd "$tempdir" > /dev/null

mv "$REPORT_FILE" "$REPORT_NAME"
zip "$REPORT_ZIP_NAME" "$REPORT_NAME"

chmod 440 *
sudo mv * "$ARCHIVE_DIR"/

popd > /dev/null

rmdir "$tempdir"

side-notes: you should always double-quote your var expansions; also, using uppercase varnames for local variables is risky because it might conflict with external or builtin variables (for ex. REPLY, SECONDS, etc...)

Fravadona
  • 13,917
  • 1
  • 23
  • 35
1

A common arrangement is to run the entire script as sudo, but have it drop its privileges once it's done.

#!/bin/bash

# Exit with an error code if one of these commands fail
set -e

chmod 440 /tmp/"$REPORT_FILE"
# this line had an error; did you mean this?
mv /tmp/"$REPORT_FILE" "/$ARCHIVE_DIR$/$REPORT_NAME"

cd "$ARHIVE_DIR"
# I'm guessing REPORT_NAME was supposed to be $REPORT_NAME?
zip "$REPORT_ZIP_NAME" "$REPORT_NAME"
chmod 440 "$REPORT_ZIP_NAME"
rm "$REPORT_NAME"

exec su - "$SUDO_USER" -c 'psql blah blah ...'

The set -e is a bit of a kludge, but I did not want to add explicit error checking for each command which requires privileged access.

Notice also When to wrap quotes around a shell variable

tripleee
  • 175,061
  • 34
  • 275
  • 318
  • In this case I would find it clearer (also for debugging) to place the part in front of your `exec` into a separate script and run *this* with sudo. – user1934428 Mar 20 '23 at 12:22