system() calls successful from script/console but silently failing in application - ruby-on-rails

Specifically calls to gpg.
I'm having a hard time tracking down the problem as the logs don't give any output for these failing calls and they work perfectly from the production console.
I've tried specifying the path to gpg:
system "path/to/gpg --all -my --encryption -options
and have made sure that Passenger is running under the same user that I am entering the console as. I've also tried backticking and %x()ing the commands in search of a more verbose response.
No luck. Prayer, dance and violence have proved equally useless.

To help debug issues like this, you could try calling a bash script which handles logging of issues, instead of the command directly:
#!/bin/bash
# my_gpg_script.sh
set -e
set -u
set -x
set -v
path/to/gpg --all -my --encryption -options > /var/log/whats_happening.log
Then call system "my_gpg_script.sh" from ruby.

Lebreeze got me on the right path, but I could never get the STDOUT to redirect to my log and ended up having to debug by tracing the whole method as suggested over here https://serverfault.com/questions/98994/suppress-gpg-reading-passphrase-from-file-descriptor-0-message
strace path/to/gpg --all -my --encryption -options 2>>/var/log/whats_happening.log
It turned out to be a path issue. I had naively thought that $PATH would be the same in the console and application as long as the environment and user were the same. Not the case. Adding some extra paths in my httpd.conf file fixed me up though.
SetEnv PATH /this/bin:/that/other/bin:/and/dont/foget/bin

Related

How to edit permissions on Heroku application?

My problem in simple terms is that I have an executable that can't be run on Heroku, because it doesn't have the right permissions.
In more details, I have a RoR application on Heroku and I want to use server pdftk. But after installing it I need to chmod the file to be able to use it. And if I run a console on Heroku dashboard, put the chmod command in and try running pdftk it works, but it works just for that temporary dyno and it doesn't work on production server.
I tried creating .profile and putting the command in and that didn't work.
I tried creating Procfile and put release: chmod u+x /app/vendor/pdftk/bin/pdftk and it didn't work.
I tried all different versions of release, web, worker...
I tried creating a .sh file and putting the command in there and then running the file and it doesn't work either.
command for setting permission: chmod u+x /app/vendor/pdftk/bin/pdftk
If you need more info, please tell me.
Any help would be appreciated.
Okay, I figured out what the problem was.
I have a pipeline from gitlab and the permissions just needed to be set through git, so that they were correct when they came to the production enviroment.
I needed to run this code:git update-index --add --chmod=+x pdftk

How to add PATH variable to sudo in Fabric

when I try to use fabric to deploy Apache server remotely using Fabric, I encountered a problem. I tried to add a new path to the PATH variable first using sudo(), then I tried to echo $PATH using sudo() too. However, I found that it looks like the new path wasn't added to PATH at all. As a result, I cannot execute the bins in that path via sudo().
[name#IP:port] Executing task 'reboot'
[name#IP:port] sudo: export PATH=$PATH:/new/path/to/add/install/bin
[name#IP:port] out: sudo password:
[name#IP:port] sudo: echo $PATH
[name#IP:port] out: sudo password:
[name#IP:port] out: /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
Could anyone tell me how to add a path variable to sudo command in Fabric? Thanks in advance.
It should be habit to always give a full path to the executable when running as root, to avoid having trojan horses being pushed into your PATH.
Setting an environment variable via export works only for the current shell session - which is the one invoked by sudo. Once your command (export, in this case) is executed, the shell exits, and takes your environment variable with it. The next time you execute sudo, a new shell (with default environment) is set up, which does know nothing about your previous export.
The configuration file /etc/sudoers usually contains an entry like Defaults env_reset, the effect of which is that environment variables set in the calling environment are not copied to the environment invoked by sudo, so calling export in your current environment and then executing sudo does not work either. This is done for security reasons (ref. 1) above).
It is possible to set up /etc/sudoers to make exceptions to 3), via env_keep. Refer to man sudoers for details. However, see 1) - it is not a good idea.
There is the -E option to sudo, which allows to keep the caller's environment (including e.g. an extended PATH), but this requires SETENV being set in /etc/sudoers. Again, refer to man sudoers for details, and be mindful of 1).
use
sudo('PATH=$PATH:/new/path/to/add/install/bin commad')

Run "passenger start" from within a shell script?

Basically, "passenger start" works fine from the terminal, but a simple script like "passenger start" doesn't work because it fails with:
*** Exception PhusionPassenger::UnknownError in PhusionPassenger::Rack::ApplicationSpawner (Could not find abstract-1.0.0 in any of the sources (Bundler::GemNotFound)) (process 19278, thread #<Thread:0x7f16dbfaf368>):
Looks to me like it can't find the gems anymore. This seems to be a very common problem on Google, but I cannot find any simple answer. I do not want to monkey patch my rails application with something like this: http://blog.ninjahideout.com/posts/the-path-to-better-rvm-and-passenger-integration (which I couldn't actually get to work, anyway)
It seems unbelievable that there's not a simple way to handle this. Why is running passenger from a shell script any different from typing it by hand?
UPDATE: basically, I fixed it by not using passenger. Instead of using "passenger start" I now use "rails server" and it works fine. Now, obviously, this doesn't "solve" the issue I was having, but it's good enough for my development needs.
I'd also like to elaborate a bit on my setup, because I think I was a bit vague.
Basically, I had this script called start_rails.sh
#!/bin/bash
cd /rails/app
passenger start
It didn't work, and I tried everything under the sun, including sourcing all of my bash files, and nothing worked. I changed it to:
#!/bin/bash
source "$HOME/.rvm/scripts/rvm"
cd /rails/app
rails s
And now it works. I can run it from an upstart script:
start on started mysql
exec sudo -u ubuntu -i /home/ubuntu/bin/start_rails.sh
However, "passenger start" still doesn't work, never has, and I guess never will =P I still don't know why there's no way to run a shell script and tell it to "run it exactly as if I was typing it in manually" because simply typing "passenger start" does work. From a shell script, it doesn't. Oh well. Life goes on.
If you can run passenger by hand without problems you are in a good position right now :).
I guess there is some problem with environment variables that are set when you log in but not when the script is run. Try to add these two lines at the beginning of your script:
source ~/.bash_profile
source ~/.bashrc

Ruby background process STDOUT is empty

I'm having a weird issue with a start-up script which runs a Sinatra script using the shell's "daemon" function. The problem is that when I run the command at the command line, I get output to STDOUT. If I run the command at the command line exactly as it is in the script -- less the daemon part -- the output is correctly redirected to the output file. However, when the startup script runs it (see below), I get stuff to the STDERR log but not to the STDOUT log.
The relevant lines of the script:
#!/bin/sh
# (which is and has been a symlink to /bin/bash
# Source function library.
. /etc/init.d/functions
# Set Some Variables
RUNAS="joeuser"
PID=/var/run/myapp.pid
LOG="/var/log/myapp/app-out.log"
ERR_LOG="/var/log/myapp/app-err.log"
APPLICATION_COMMAND="RAILS_ENV=production ruby /opt/myapp/lib/daemons/my-sinatra-app.rb -p 8002 2>>${ERR_LOG} >>${LOG} &"
# Snip a bunch. This is the applicable line from the "start" case:
daemon --user $RUNAS --pidfile $PID $APPLICATION_COMMAND &> /dev/null
Now, the funky parts:
The error log is written to correctly via the redirect of STDERR.
If I reverse the order of the >> and the 2>> (I'm grasping at straws, here!), the behavior does not change: I still get STDERR logged correctly and STDOUT is empty.
If the output log doesn't exist, the STDOUT redirect creates the file. But, the file remains 0-length.
This used to work. The log directory is maintained by log-rotate. All of the more-recent 'out' logs are 0-length. The older ones are not. It seems like it stopped working some time in April. The ruby code didn't change at any time near then; neither did the startup script.
We're running three different services in this way. Two of them are ruby daemons (one uses sinatra, one does not) and the other is a background java process. This is occurring for BOTH of the ruby processes but is not happening on the java process. Maybe something changed in Ruby?
FTR, we've got ruby 1.8.5 and RHEL 5.4.
I've done some more probing. The daemon function does a bunch of stuff, but the meat of the matter is that it runs the program using runuser. The command essentially looks like this:
runuser -s /bin/bash - joeuser -c "ulimit -S -c 0 >/dev/null 2>&1 ; RAILS_ENV=production ruby /opt/myapp/lib/daemons/my-sinatra-app.rb -p 8002 '</dev/null' '>>/var/log/myapp/app-out.log' '2>>/var/log/myapp/app-err.log' '&'"
When I run exactly that at the command line (both with and without the single-ticks that got added somewhere along the line), I get the exact same screwy behavior w.r.t. the output log. So, it seems to me that this is an issue of how ruby (?) interacts with runuser?
Too long to put in a comment :-)
change the shebang to add #!/bin/sh -x and verify that everything is expanded according to your expectations. Also, when executing from terminal, your .bashrc file is sourced, when executing from script, it is not; might be something in you're environment that differ. One way to find out is to do env from terminal and from script and diff the output
env > env_terminal
env > env_script
diff env_terminal env_script
Happy hunting...

Bash Command which Rails does Not Find

Passenger says:
Ruby on Rails application could not be started
...
Command 'exiftool' not found (MiniExiftool::Error)
When I login with ssh and I type exiftool in any directory the command works properly.
I have the follwing line in both .bash_profile and .bashrc
export PATH=$PATH:$HOME/bin
Is it possible that Rails (MiniExiftool plugin) does not recognize that bash command? How can I fix this behaviour?
The PATH for the user your server runs as does not include the directory that exiftool is in. You can either add it to that user's path, or you can refer to exiftool using its full path. I'd recommend this second approach for reasons of security. There are a number of attacks that involve putting trojan horses in a user's path ahead of the directories where the real binaries live.

Resources