Why command -- sh raise error? - shell

Why the shell command raises error:
sudo -u postgres \
-- sh -c '/usr/bin/env psql -c "CREATE ROLE deploy PASSWORD secret SUPERUSER CREATEDB CREATEROLE INHERIT LOGIN;"'
Causes:
ERROR: syntax error at end of input
LINE 1: CREATE
^
What's right syntax ?
Many thanks.

Try:
sudo -u postgres '/usr/bin/env RBENV_ROOT=/usr/local/rbenv RBENV_VERSION=2.1.3 psql -c "CREATE ROLE deploy PASSWORD secret SUPERUSER CREATEDB CREATEROLE INHERIT LOGIN;"'
env takes variable assignments before the command to run. And I don't see why you need to use sh -c, sudo executes the command for you.

Related

Using sshpass to run a command on another server

I'm trying to run a single command on server X, to have that SSH into server Y and run another command
I'm doing this like the below:
sshpass -p 'my_password' ssh -t test-admin#my_ip "sudo su c command_must_be_run_root --arguments"
So to break it down:
I'm using "sshpass" to pass a password into my ssh command
I'm SSH'ing into the new server as the "test-admin" user
once in the server, I am running the command "sudo su command_must_be_run_root --arguments
This "command_must_be_run_root" is a command that has to be run as root only
It also has arguments I have to pass in. However I'm seeing that when I pass in the arguments, it is passing these arguments into the "su" command, and not passing them into the new command I want to run
Any ideas on how to fix this?
For what ever reason when you have a command with arguments you need to actually tell sudo su to login as root. Without logging in first it will run the first part of the command, even with all of it in single quotes, but not the args. (I guess it thinks that is the end of the command or it's only 1 command per sudo su -c, and that is why the persistent login works?). After adding sudo su -l root then you can continue with -c and everything that follows needs single quotes.
Should look like this:
sshpass -p 'my_password' ssh -t test-admin#my_ip "sudo su -l root -c 'command_ran_as_root --arguments'"
I don't think that su command is valid in any case. The syntax of su is su <someuser> [arguments...], so what you've written is going to try running command_must_be_run_root as user c.
I suspect that c is supposed to be -c, in which case you need to quote the arguments to -c, which would solve the problem you're asking about:
sshpass -p 'my_password' ssh -t test-admin#my_ip "sudo su -c 'command_must_be_run_root --arguments'"
But the next question is, if you already have sudo access, why are you bothering with su? You could just write instead:
sshpass -p 'my_password' ssh -t test-admin#my_ip sudo command_must_be_run_root --arguments

change user and execute one command under bash

Basically, I want to switch to user postgres and get a listing of databases. This is with a Fabric script that reads command lines from a text file one by one, executes them and then saves their output to file.
su - postgres && psql -c '\l'
When I do this under bash directly:
(ssha)root ~$su - postgres && psql -c '\l'
postgres#localvm:~$
I saw a related question, linux - Executing multiple commands under as another username within a file in BASH shell, but that wouldn't work with my 1-line-per-command scheme and I don't need a full script, just 1 command.
You can use su -c:
su - postgres -c "psql -c '\l'"
Though often you'll also have sudo, which is more robust and easier to use:
sudo -u postgres psql -c '\l'

How to get the output of ssh when the command has a command to change user

When I use ssh to run command on a remote machine, I will get the output from shell. However, if I add
sudo su - user2
I will get no output. Now, I cannot do
ssh user2#host
Because of some permission issue.
Is there any way to get the output for the following command?
ssh user1#host 'sudo su - user2; wc -l tmp.txt'
Thanks to #laenkeio. Using sudo -u user2 can run some simple programs.
However, when I need to call a python script which needs some enviroment variable for user2, the script was not able to find those default path by using sudo -u user2.
If you have the appropriate sudo rights on host you should be able to do it with:
ssh -t user1#host 'sudo -u user2 wc -l tmp.txt'
Using sudo -u means "execute as user2", thus avoiding the extra su -. And -t forces ssh to allocate a tty so that sudo can ask for your password.
If you cannot do ssh user2#host for some permission issue, you'll not be able to run ssh user1#host 'sudo su - user2; ... for the same reason...
And, even with no permission issue, when doing su - user you'll be requested for a password...

How can I run one line of bash shell script as a specific user

I have a script I run manually (let's say) mylogin. But there's one line that needs to run as user postgres.
What is a good way to do that?
It's ok if I get a password prompt. I just need it to work somehow.
Here's what I have so far...
~/reload_test_data.sh
#!/bin/bash
# Here's the part that needs to run as user `postgres`...
sudo su postgres
export PGDATA=/Library/PostgreSQL/9.4/data && pg_ctl -m fast restart
# And here we should go back to `mylogin`...
cd ~/projects/my_project
echo 'Dropping database'
bundle exec rake db:drop
# More stuff etc...
I'm using Mac OS 10.12.1.
One of the arguments for sudo is the command so you can do something like:
sudo -u <user> bash -c "command_1; command_2; etc"
where -u <user> change to your target user

How to use not_if in a chef recipe

I am new to chef so I am a little confused in how the conditional not_if works inside a execute resource. I understand that it tells chef not to execute a command if the command returns 0 or true; however, in my code it is apparently still running the command.
The following code is supposed to create a user (and its password) and a database; however, if the user and database already exist, it should not do anything. The user, database and password are defined in the attributes. The following is the code I have:
execute "create-user" do
code = <<-EOH
psql -U postgres -c "select * from pg_user where usename='#{node[:user]}'" | grep -c #{node[:user]}
EOH
user "postgres"
command "createuser -s #{node[:user]}"
not_if code
end
execute "set-user-password" do
user "postgres"
command "psql -U postgres -d template1 -c \"ALTER USER #{node[:user]} WITH PASSWORD '#{node[:password]}';\""
end
execute "create-database" do
exists = <<-EOH
psql -U postgres -c "select * from pg_database WHERE datname='#{node[:database]}'" | grep -c #{node[:database]}}
EOH
user "postgres"
command "createdb #{node[:database]}"
not_if exists
end
Chef gives me the following error:
Error executing action run on resource 'execute[create-user]'
...
[2013-01-25T12:24:51-08:00] FATAL: Mixlib::ShellOut::ShellCommandFailed: execute[create-user] (postgresql::initialize line 16) had an error: Mixlib::ShellOut::ShellCommandFailed: Expected process to exit with [0], but received '1'
STDERR: createuser: creation of new role failed: ERROR: role "user" already exists
To me it seems that it should work;however, it still running the execute. Am I missing something?
Thank you
I had been having the same issue. But, in my case, "not_if" seems executed by different user (root), and failed to check the condition properly. Adding [:user => "postgres"] resolved the issue.
execute "create-database-user" do
user "postgres"
exists = <<-EOH
psql -U postgres -c "select * from pg_user where usename='#{settings[:username]}'" | grep -c #{settings[:username]}
EOH
command "createuser -U postgres -sw #{settings[:username]}"
not_if exists, :user => "postgres"
end
I've referred the following code example.
https://github.com/MarcinKoziuk/chef-postgres-dbsetup/blob/master/recipes/default.rb
You're checking for the existence of:
node[:user]
If it doesn't exist, you create:
node[:postgresql][:user]
Unless these happen to be equal, you'll keep trying to create node[:postgresql][:user] repeatedly.
First, there is a typo in the WHERE condition. It should probably be username instead of usename.
Anyawy, you should do:
execute "create-user" do
user "postgres"
command "createuser -s #{node[:user]}"
not_if "psql -U postgres -c \"select * from pg_user where username='#{node[:user]}'\" | grep -c #{node[:user]}"
end
This assumes that your psql -U postgres -c "select * from pg_user where username='#{node[:user]}'" is correct.
Same with a database:
execute "create-database" do
user "postgres"
command "createdb #{node[:database]}"
not_if "psql -U postgres -c \"select * from pg_database WHERE datname='#{node[:database]}'\" | grep -c #{node[:database]}}"
end
Regarding the username, even if it already exists, changing the password to the known one shouldn't cause a problem. After all you know the password.
FYI, you can define multiple conditionals within one resource.
Good luck with Chef! I love it very much!

Resources