0

I restore my database template on Linux as shown as: Linux teminal:

su postgres
psql
create database test3;
\q
pg_restore -v -d test3 /opt/empty-db_template.backup
exit
systemctl restart postgresql-11.service

And done!. But when I Executing Shell Commands in python as shown as Get stuck in psqlstep, How can I fix it?

Get stuck in psql step

import os
os.system('ls')
os.system('su postgres')
os.system('psql')

os.system('create database test3;')
os.system('\q')


os.system('pg_restore -v -d test3 /opt/empty-db_template.backup')
os.system('exit')
os.system('systemctl restart postgresql-11.service')
mr boy
  • 3
  • 1
  • 1
    you got os.system wrongly. It is not passing your strings as keystrokes, but executes argument as the command line. So, for example, os.system('\q') does not have any sense. You should make all your operations as one command line. So you will have three os.system calls (one for 'ls', second for running psql and third to restart postgresql) – user3431635 May 03 '21 at 06:32
  • 1
    Possible duplicate of https://stackoverflow.com/questions/37586811/pass-commands-as-input-to-another-command-su-ssh-sh-etc – tripleee May 03 '21 at 06:39

2 Answers2

0

What you're doing here cannot work. su creates a new shell. It will be waiting for more input form the console. You won't get the chance to enter the psql command until you have exited the su shell. You either need to run this command as the postgres user, or use the su command repeatedly, or just create a shell script and run the shell script.

os.system( 'su postgres createdb test3' )
os.system( 'su postgres pg_restore ... ' )
os.systen( 'systemctl restart postgresql-11.service' )
Tim Roberts
  • 48,973
  • 4
  • 21
  • 30
  • In addition, you'll probably want to replace `os.system()` with `subprocess.run()` or one of its legacy precursors (in particular, `subprocess.check_call()`. You can get away with a single subprocess with `shell=True`, though you'll still need to figure out how to properly script these commands. – tripleee May 03 '21 at 06:40
0

The su postgres switches to another user and opens a subshell wherein the following commands are executed. In other words, you execute the commands (until the exit) as user postgres.

With the os.system() you leave the shell the su is opening at once. The following commands are executed as your standard user again.

To avoid this, you will have to pass all commands to su directly as in

su postgres -c psql

And I take it that the line create database test3 isn't a shell command but a line entered into the interactive psql command. Then you will have to figure out how to do that non-interactively, e.g. by calling psql -c 'create database test3' or similar. Consult the man page of psql for details.

So effectively you will use a line like

os.system('su postgres -c "psql -c \'create database test3\'"')

Quoting can be an issue. Try around and if you don't succeed, open another question with more specific information on what you already tried.

Alfe
  • 56,346
  • 20
  • 107
  • 159
  • 1
    Thanks help me, I create database:`os.system('su postgres -c "psql -c \'create database test3\'"')` and restore my template: `os.system('su postgres -c "pg_restore -v -d test3 /opt/empty-db_template.backup" ')` and finish. Not need `os.system('\q')` and `os.system('exit')` – mr boy May 05 '21 at 09:16
  • Yes, the `\q` will exit the interactive mode of postgres and the `exit` leaves the shell. Both are obviously not necessary if you use the new approach. Using `-c` to `su` terminates the shell after executing the command (so no `exit` needed) and calling `psql` with `-c` also executes one command and then terminates (so no `\q` needed). – Alfe May 05 '21 at 11:52