הפעלת פקודות rails מ-Bash המארח

סיכום מבוסס בינה מלאכותית

The user sven2 seeks help executing Rails commands from the host Bash to automate user cleanup in a Discourse installation. They encounter Redis connection issues when using launcher run app and later face command execution errors with docker exec. pfaffman suggests using docker exec instead of launcher. supermathie clarifies that the issue stems from incorrect command quoting, explaining that rails console should be passed as a single argument and recommending rails runner for one-off commands. sven2 acknowledges the solution and thanks the community.

Hi all,

I want to execute automated user clean up tasks from the host Bash. Manually, I run

/var/discourse/launcher enter app
rails c
UserDestroyer.new(Discourse.system_user).destroy(User.find_by_username_or_email("user@example.com"), delete_posts: false) 

I have a long list of user names from a text file that need to be removed. Manually executing this is not reasonable. I tried to wrap the deletion command in a bash script. When executing rails c with the launcher app subcommand, the Redis connection fails:

/var/discourse/launcher run app "echo \"User.find_by_username_or_email('user@example.com')\" | rails c"
Failed to report error: Error connecting to Redis on localhost:6379 (Errno::EADDRNOTAVAIL) 2 Error connecting to Redis on localhost:6379 (Errno::EADDRNOTAVAIL) subscribe failed, reconnecting in 1 second.

However, when I compare the environments with export between launcher enter app and launcher run app, they look pretty much identical. What am I missing? launcher run starts in / while launcher enter directly enters /var/www/discourse. Using a cd before executing rails does not help.

Any hints? Thanks!

I think docker run launches a new container.

For things like that I use docker exec rather than launcher,which does a bunch of stuff you don’t need.

Thanks for the reply. I find that the behavior of rails with docker exec is also very odd. Manually, it works perfectly well:

docker exec -it de7f5f6f649c '/bin/bash'
root@discourse-app:/# rails c
[1] pry(main)> User.find_by_username_or_email('myname')

But when I try to execute rails c from outside the container, I get the following problems:

docker exec -it de7f5f6f649c "/usr/local/bin/rails console"
OCI runtime exec failed: exec failed: container_linux.go:367: starting container process caused: exec: "/usr/local/bin/rails console": stat /usr/local/bin/rails console: no such file or directory: unknown

But more interesting:

docker exec -it de7f5f6f649c '/bin/bash -c "/usr/local/bin/rails"'
OCI runtime exec failed: exec failed: container_linux.go:367: starting container process caused: exec: "/bin/bash -c \"/usr/local/bin/rails\"": stat /bin/bash -c "/usr/local/bin/rails": no such file or directory: unknown

Why is this different at all?

This is expected; you are telling docker to execute the binary /usr/local/bin/rails console in the container. That is, a single file with an embedded space. This file doesn’t exist.

consider the following:

○ → docker run -i debian /bin/echo hello
hello

○ → docker run -i debian '/bin/echo hello'
docker: Error response from daemon: OCI runtime create failed: container_linux.go:367: starting container process caused: exec: "/bin/echo hello": stat /bin/echo hello: no such file or directory: unknown.
ERRO[0000] error waiting for container: context canceled 

Quote the command the same way as if you were executing from inside the container:

○ → docker exec -i app rails runner 'puts "hello"'
hello

Using the example from the OP, this should work:

docker exec -i app rails runner 'UserDestroyer.new(Discourse.system_user).destroy(User.find_by_username_or_email("user@example.com"), delete_posts: false)'

Okay, it was unexpected for me because I did not RTFM. Thanks for the fast help.