호스트 Bash에서 rails 명령 실행

모두 안녕하세요,

호스트 Bash에서 자동화된 사용자 정리 작업을 실행하려고 합니다. 수동으로 실행할 때는 다음을 사용합니다.

/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) 

삭제해야 할 사용자 이름이 담긴 텍스트 파일에 긴 목록이 있습니다. 수동으로 이 작업을 수행하는 것은 비현실적입니다. 삭제 명령을 bash 스크립트로 감싸서 실행해 보았지만, launcher app 하위 명령으로 rails c를 실행할 때 Redis 연결이 실패합니다:

/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.

그러나 launcher enter app와 launcher run app 사이의 환경을 export 명령으로 비교해 보면 거의 동일해 보입니다. 제가 놓치고 있는 것이 무엇일까요? launcher run은 / 디렉터리에서 시작되는 반면, launcher enter는 /var/www/discourse로 직접 진입합니다. rails 실행 전에 cd 명령을 사용하여 디렉터리를 변경해도 도움이 되지 않습니다.

힌트가 있을까요? 감사합니다!

docker run이 새 컨테이너를 시작한다고 생각합니다.

이런 용도로는 launcher 대신 docker exec를 사용합니다. launcher는 필요하지 않은 일들을 꽤 많이 수행하거든요.

답변해 주셔서 감사합니다. docker exec를 사용할 때 rails의 동작 방식도 매우 이상하다고 느낍니다. 수동으로 실행하면 완벽하게 잘 작동합니다:

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

하지만 컨테이너 밖에서 rails c를 실행하려고 하면 다음과 같은 문제가 발생합니다:

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

더 흥미로운 점은 다음과 같습니다:

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

왜 이런 차이가 나는 걸까요?

이는 예상된 결과입니다. Docker에 컨테이너에서 바이너리 /usr/local/bin/rails console를 실행하라고 지시하고 있기 때문입니다. 즉, 공백이 포함된 단일 파일입니다. 이러한 파일은 존재하지 않습니다.

다음과 같은 사항을 고려해 보세요:

○ → 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 

컨테이너 내부에서 실행하는 것과 동일한 방식으로 명령을 따옴표로 묶어야 합니다:

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

질문자(OP)의 예를 사용하면 다음과 같이 작동해야 합니다:

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

음, RTFM을 하지 않아서 그런지 내게는 의외였어요. 빠른 도움 주셔서 감사합니다.