- Rails 콘솔 세션 시작하기
- Active Record 로깅 활성화
- 속성
- 데이터베이스 문(statement) 타임아웃 비활성화
- Rails 콘솔 세션 기록 출력
- Rails Runner 사용하기
- 객체에 대한 특정 메소드 찾기
- 메서드 소스 찾기
- 출력 제한
- 마지막 작업의 결과 가져오기 또는 저장하기
- 작업 시간 측정
- Active Record 객체
- Active Record 모델을 사용하여 데이터베이스 쿼리하기
- 문제 해결
Rails 콘솔
GitLab의 핵심은 Ruby on Rails 프레임워크를 사용하여 구축된 웹 애플리케이션입니다.
Rails 콘솔은 명령줄에서 GitLab 인스턴스와 상호작용할 수 있는 방법을 제공하며, Rails에 내장된 놀라운 도구에 접근할 수 있는 권한도 부여합니다.
Rails 콘솔은 문제를 해결하고 있거나 GitLab 애플리케이션에 직접 접근하여만 데이터를 검색해야 하는 GitLab 시스템 관리자용입니다. 기본적인 Ruby 지식이 필요합니다 (빠른 소개를 위해 이 30분 튜토리얼을 시도해 보세요). Rails 경험은 유용하지만 필수는 아닙니다.
Rails 콘솔 세션 시작하기
Rails 콘솔 세션을 시작하는 과정은 GitLab 설치 유형에 따라 다릅니다.
sudo gitlab-rails console
docker exec -it <container-id> gitlab-rails console
sudo -u git -H bundle exec rails console -e production
# 포드 찾기
kubectl get pods --namespace <namespace> -lapp=toolbox
# Rails 콘솔 열기
kubectl exec -it -c toolbox <toolbox-pod-name> -- gitlab-rails console
콘솔을 종료하려면 quit
를 입력하십시오.
자동 완성 비활성화
Ruby 자동 완성은 터미널을 느리게 만들 수 있습니다. 다음을 원하시면:
- 자동 완성을 비활성화하려면
Reline.autocompletion = IRB.conf[:USE_AUTOCOMPLETE] = false
를 실행하십시오. - 자동 완성을 다시 활성화하려면
Reline.autocompletion = IRB.conf[:USE_AUTOCOMPLETE] = true
를 실행하십시오.
Active Record 로깅 활성화
Rails 콘솔 세션에서 Active Record 디버그 로깅 출력을 활성화하려면 다음을 실행하십시오:
ActiveRecord::Base.logger = Logger.new($stdout)
기본적으로 이전 스크립트는 표준 출력에 로깅합니다. 출력 리디렉션을 위해 로그 파일을 지정할 수 있으며, $stdout
을 원하는 파일 경로로 교체하면 됩니다. 예를 들어, 이 코드는 /tmp/output.log
로 모든 것을 로깅합니다:
ActiveRecord::Base.logger = Logger.new('/tmp/output.log')
이것은 콘솔에서 실행할 수 있는 Ruby 코드에 의해 트리거된 데이터베이스 쿼리에 대한 정보를 보여줍니다. 로깅을 다시 끄려면 다음을 실행하십시오:
ActiveRecord::Base.logger = nil
속성
사용 가능한 속성을 보기 위해 pretty print(pp
)를 사용합니다.
예를 들어, 사용자 이름과 이메일 주소가 포함된 속성을 확인합니다:
u = User.find_by_username('someuser')
pp u.attributes
부분 출력:
{"id"=>1234,
"email"=>"someuser@example.com",
"sign_in_count"=>99,
"name"=>"S User",
"username"=>"someuser",
"first_name"=>nil,
"last_name"=>nil,
"bot_type"=>nil}
그런 다음 속성을 사용하여 SMTP 테스트와 같은 작업을 수행합니다:
e = u.email
n = u.name
Notify.test_email(e, "테스트 이메일 for #{n}", '테스트 이메일').deliver_now
#
Notify.test_email(u.email, "테스트 이메일 for #{u.name}", '테스트 이메일').deliver_now
데이터베이스 문(statement) 타임아웃 비활성화
현재 Rails 콘솔 세션에서 PostgreSQL 문(statement) 타임아웃을 비활성화할 수 있습니다.
GitLab 15.11 및 이전 버전에서는 데이터베이스 문(statement) 타임아웃을 비활성화하려면 다음을 실행합니다:
ActiveRecord::Base.connection.execute('SET statement_timeout TO 0')
GitLab 16.0 및 이후 버전에서는 기본적으로 GitLab이 두 개의 데이터베이스 연결을 사용합니다. 데이터베이스 문(statement) 타임아웃을 비활성화하려면 다음을 실행합니다:
ActiveRecord::Base.connection.execute('SET statement_timeout TO 0')
Ci::ApplicationRecord.connection.execute('SET statement_timeout TO 0')
GitLab 16.0 및 이후 버전에서 단일 데이터베이스 연결을 사용하도록 재구성된 인스턴스는 GitLab 15.11 및 이전 버전의 코드를 사용하여 데이터베이스 문(statement) 타임아웃을 비활성화해야 합니다.
데이터베이스 문(statement) 타임아웃을 비활성화하면 현재 Rails 콘솔 세션에만 영향을 미치며, GitLab 프로덕션 환경이나 다음 Rails 콘솔 세션에서는 유지되지 않습니다.
Rails 콘솔 세션 기록 출력
Rails 콘솔에서 다음 명령어를 입력하여 명령어 기록을 표시합니다.
puts Reline::HISTORY.to_a
그 후, 클립보드에 복사하여 향후 참고를 위해 저장할 수 있습니다.
Rails Runner 사용하기
GitLab 프로덕션 환경의 컨텍스트에서 일부 Ruby 코드를 실행해야 하는 경우, Rails Runner를 사용하여 수행할 수 있습니다.
스크립트 파일을 실행할 때, 해당 스크립트는 git
사용자에 의해 접근 가능해야 합니다.
명령어 또는 스크립트가 완료되면, Rails Runner 프로세스가 종료됩니다.
예를 들어 다른 스크립트나 크론 작업에서 실행하는 데 유용합니다.
-
Linux 패키지 설치의 경우:
sudo gitlab-rails runner "RAILS_COMMAND" # 두 줄 Ruby 스크립트 예시 sudo gitlab-rails runner "user = User.first; puts user.username" # Ruby 스크립트 파일 예시 (전체 경로 사용해야 함) sudo gitlab-rails runner /path/to/script.rb
-
자체 컴파일된 설치의 경우:
sudo -u git -H bundle exec rails runner -e production "RAILS_COMMAND" # 두 줄 Ruby 스크립트 예시 sudo -u git -H bundle exec rails runner -e production "user = User.first; puts user.username" # Ruby 스크립트 파일 예시 (전체 경로 사용해야 함) sudo -u git -H bundle exec rails runner -e production /path/to/script.rb
Rails Runner는 콘솔과 동일한 출력을 생성하지 않습니다.
콘솔에서 변수를 설정하면, 콘솔은 변수 내용이나 참조된 엔티티의 속성과 같은 유용한 디버그 출력을 생성합니다:
irb(main):001:0> user = User.first
=> #<User id:1 @root>
Rails Runner는 이러한 작업을 수행하지 않으므로, 출력을 생성하는 데 명시적이어야 합니다:
$ sudo gitlab-rails runner "user = User.first"
$ sudo gitlab-rails runner "user = User.first; puts user.username ; puts user.id"
root
1
Ruby에 대한 기본 지식은 매우 유용합니다. 빠른 소개를 위해 이 30분 튜토리얼을 시도해 보세요.
Rails 경험은 도움이 되지만 필수는 아닙니다.
객체에 대한 특정 메소드 찾기
Array.methods.select { |m| m.to_s.include? "sing" }
Array.methods.grep(/sing/)
메서드 소스 찾기
instance_of_object.method(:foo).source_location
# 예시: project.private?를 호출하는 경우
project.method(:private?).source_location
출력 제한
문장 끝에 세미콜론(;
)과 후속 문장을 추가하면 기본적인 암시적 반환 출력을 방지할 수 있습니다. 이 방법은 이미 세부 정보를 명시적으로 출력하고 있으며, 잠재적으로 많은 반환 출력이 있는 경우에 사용할 수 있습니다:
puts ActiveRecord::Base.descendants; :ok
Project.select(&:pages_deployed?).each {|p| puts p.path }; true
마지막 작업의 결과 가져오기 또는 저장하기
언더스코어(_
)는 이전 문장의 암시적 반환을 나타냅니다. 이를 사용하여 이전 명령의 출력에서 변수를 빠르게 할당할 수 있습니다:
Project.last
# => #<Project id:2537 root/discard>>
project = _
# => #<Project id:2537 root/discard>>
project.id
# => 2537
작업 시간 측정
하나 이상의 작업의 소요 시간을 측정하려면 다음 형식을 사용하세요. <operation>
자리 표시자를 선택한 Ruby 또는 Rails 명령어로 바꾸어 주세요:
# 단일 작업
Benchmark.measure { <operation> }
# 여러 작업의 세부 내용
Benchmark.bm do |x|
x.report(:label1) { <operation_1> }
x.report(:label2) { <operation_2> }
end
추가 정보는 우리의 벤치마크에 대한 개발자 문서를 확인하세요.
Active Record 객체
데이터베이스에 저장된 객체 검색
Rails는 내부적으로 Active Record,
객체-관계 매핑 시스템을 사용하여 애플리케이션 객체를 읽고 쓰며 PostgreSQL 데이터베이스에 매핑합니다. 이러한 매핑은 Rails 애플리케이션에 정의된 Ruby 클래스인 Active Record 모델에 의해 관리됩니다. GitLab의 경우 모델 클래스는 /opt/gitlab/embedded/service/gitlab-rails/app/models
에 있습니다.
기본 데이터베이스 쿼리를 볼 수 있도록 Active Record에 대한 디버그 로깅을 활성화해봅시다:
ActiveRecord::Base.logger = Logger.new($stdout)
이제 데이터베이스에서 사용자를 검색해 봅시다:
user = User.find(1)
다음과 같은 결과가 반환됩니다:
D, [2020-03-05T16:46:25.571238 #910] DEBUG -- : User Load (1.8ms) SELECT "users".* FROM "users" WHERE "users"."id" = 1 LIMIT 1
=> #<User id:1 @root>
id
열 값이 1
인 행을 데이터베이스의 users
테이블에서 쿼리했음을 알 수 있으며, Active Record는 해당 데이터베이스 레코드를 상호작용할 수 있는 Ruby 객체로 변환했습니다. 다음을 시도해보세요:
user.username
user.created_at
user.admin
관례상, 열 이름은 Ruby 객체 속성으로 직접 변환됩니다. 그래서 user.<column_name>
을 사용하여 속성 값을 확인할 수 있습니다.
또한 관례상, Active Record 클래스 이름(단수형 및 카멜 케이스)은 테이블 이름(복수형 및 스네이크 케이스)과 직접적으로 매핑됩니다. 예를 들어, users
테이블은 User
클래스와 매핑되고, application_settings
테이블은 ApplicationSetting
클래스와 매핑됩니다.
테이블 및 열 이름 목록은 /opt/gitlab/embedded/service/gitlab-rails/db/schema.rb
에 있는 Rails 데이터베이스 스키마에서 확인할 수 있습니다.
속성 이름으로 데이터베이스에서 객체를 검색할 수도 있습니다:
user = User.find_by(username: 'root')
다음과 같은 결과가 반환됩니다:
D, [2020-03-05T17:03:24.696493 #910] DEBUG -- : User Load (2.1ms) SELECT "users".* FROM "users" WHERE "users"."username" = 'root' LIMIT 1
=> #<User id:1 @root>
다음 사항을 시도해보세요:
User.find_by(username: 'root')
User.where.not(admin: true)
User.where('created_at < ?', 7.days.ago)
마지막 두 명령이 여러 User
객체를 포함하는 ActiveRecord::Relation
객체를 반환한 것을 알아차렸나요?
지금까지 우리는 .find
또는 .find_by
를 사용해왔습니다. 이러한 메서드는 단일 객체만 반환하도록 설계되었습니다 (생성된 SQL 쿼리에서 LIMIT 1
을 주목하세요). .where
는 객체 컬렉션을 얻고자 할 때 사용됩니다.
비관리자 사용자 컬렉션을 가져와 봅시다:
users = User.where.not(admin: true)
다음과 같은 결과가 반환됩니다:
D, [2020-03-05T17:11:16.845387 #910] DEBUG -- : User Load (2.8ms) SELECT "users".* FROM "users" WHERE "users"."admin" != TRUE LIMIT 11
=> #<ActiveRecord::Relation [#<User id:3 @support-bot>, #<User id:7 @alert-bot>, #<User id:5 @carrie>, #<User id:4 @bernice>, #<User id:2 @anne>]>
이제 다음을 시도해 보세요:
users.count
users.order(created_at: :desc)
users.where(username: 'support-bot')
마지막 명령에서 우리는 더 복잡한 쿼리를 생성하기 위해 .where
문을 연결할 수 있음을 알 수 있습니다. 또한 반환된 컬렉션이 단일 객체만 포함하고 있지만 직접 상호작용할 수는 없다는 것을 주목하세요:
users.where(username: 'support-bot').username
다음과 같은 결과가 반환됩니다:
Traceback (most recent call last):
1: from (irb):37
D, [2020-03-05T17:18:25.637607 #910] DEBUG -- : User Load (1.6ms) SELECT "users".* FROM "users" WHERE "users"."admin" != TRUE AND "users"."username" = 'support-bot' LIMIT 11
NoMethodError (undefined method `username' for #<ActiveRecord::Relation [#<User id:3 @support-bot>]>)
Did you mean? by_username
컬렉션에서 단일 객체를 가져오기 위해 .first
메서드를 사용하여 컬렉션의 첫 번째 항목을 가져옵시다:
users.where(username: 'support-bot').first.username
이제 우리가 원하는 결과를 얻었습니다:
D, [2020-03-05T17:18:30.406047 #910] DEBUG -- : User Load (2.6ms) SELECT "users".* FROM "users" WHERE "users"."admin" != TRUE AND "users"."username" = 'support-bot' ORDER BY "users"."id" ASC LIMIT 1
=> "support-bot"
Active Record를 사용하여 데이터베이스에서 데이터를 검색하는 다양한 방법에 대한 더 많은 정보는 Active Record 쿼리 인터페이스 문서를 참조하세요.
Active Record 모델을 사용하여 데이터베이스 쿼리하기
m = Model.where('attribute like ?', 'ex%')
# 예를 들어 프로젝트를 쿼리하기 위해
projects = Project.where('path like ?', 'Oumua%')
Active Record 객체 수정하기
이전 섹션에서는 Active Record를 사용하여 데이터베이스 레코드를 검색하는 방법에 대해 배웠습니다. 이제는 데이터베이스에 변경사항을 작성하는 방법을 배워보겠습니다.
먼저, root
사용자를 검색해 보겠습니다:
user = User.find_by(username: 'root')
다음으로, 사용자의 비밀번호를 업데이트해 보겠습니다:
user.password = 'password'
user.save
이렇게 하면 다음과 같이 반환됩니다:
Enqueued ActionMailer::MailDeliveryJob (Job ID: 05915c4e-c849-4e14-80bb-696d5ae22065) to Sidekiq(mailers) with arguments: "DeviseMailer", "password_change", "deliver_now", #<GlobalID:0x00007f42d8ccebe8 @uri=#<URI::GID gid://gitlab/User/1>>
=> true
여기서 .save
명령이 true
를 반환하여 비밀번호 변경이 성공적으로 데이터베이스에 저장되었음을 나타냅니다.
우리는 또한 저장 작업이 다른 작업을 트리거했음을 알 수 있습니다. 이 경우 이메일 알림을 전달하기 위한 백그라운드 작업입니다. 이는 Active Record 콜백의 예입니다. 해당 콜백은 Active Record 객체 생명 주기의 이벤트에 반응하여 실행되도록 지정된 코드입니다. 이러한 이유로, 데이터에 직접 변경이 필요할 때 Rails 콘솔을 사용하는 것이 선호됩니다. 직접 데이터베이스 쿼리를 통해 이루어진 변경은 이러한 콜백을 트리거하지 않기 때문입니다.
속성을 한 줄로 업데이트하는 것도 가능합니다:
user.update(password: 'password')
또한 여러 속성을 한 번에 업데이트할 수 있습니다:
user.update(password: 'password', email: 'hunter2@example.com')
이제 다른 것을 시도해 보겠습니다:
# 최신 상태를 얻기 위해 다시 객체를 검색합니다
user = User.find_by(username: 'root')
user.password = 'password'
user.password_confirmation = 'hunter2'
user.save
이것은 false
를 반환하여 우리가 한 변경사항이 데이터베이스에 저장되지 않았음을 나타냅니다. 아마도 그 이유를 짐작할 수 있겠지만, 확실히 알아봅시다:
user.save!
이 코드를 실행하면 다음과 같은 결과가 나올 것입니다:
Traceback (most recent call last):
1: from (irb):64
ActiveRecord::RecordInvalid (Validation failed: Password confirmation doesn't match Password)
아하! 우리는 Active Record 유효성 검사를 통과했습니다.
유효성 검사는 데이터베이스에 원하지 않는 데이터가 저장되는 것을 방지하기 위해 애플리케이션 레벨에서 설정된 비즈니스 로직입니다. 대부분의 경우 문제 입력을 수정하는 방법에 대해 알려주는 유용한 메시지도 함께 제공됩니다.
우리는 또한 .update
에 뱅(!)을 추가할 수 있습니다:
user.update!(password: 'password', password_confirmation: 'hunter2')
Ruby에서는 !
로 끝나는 메서드 이름을 흔히 “뱅 메서드”라 부릅니다. 관례적으로, 뱅은 메서드가 작용하는 객체를 직접 수정함을 나타내며, 변형된 결과를 반환하고 기본 객체는 그대로 둡니다. 데이터베이스에 쓰는 Active Record 메서드의 경우 뱅 메서드는 발생한 오류가 있을 때 단순히 false
를 반환하는 것이 아니라 명시적인 예외를 발생시킵니다.
유효성 검사를 완전히 건너뛰는 것도 가능합니다:
# 최신 상태를 얻기 위해 다시 객체를 검색합니다
user = User.find_by(username: 'root')
user.password = 'password'
user.password_confirmation = 'hunter2'
user.save!(validate: false)
이는 권장되지 않으며, 유효성 검사는 일반적으로 사용자 제공 데이터의 무결성과 일관성을 보장하기 위해 설정됩니다.
유효성 검사 오류는 전체 객체가 데이터베이스에 저장되는 것을 방지합니다. 폼을 제출할 때 GitLab UI에서 신비로운 빨간 배너가 표시되는 경우, 문제의 근본 원인에 도달하는 가장 빠른 방법이 될 수 있습니다.
Active Record 객체와 상호작용하기
하루의 끝에 Active Record 객체는 그냥 일반 Ruby 객체입니다.
따라서, 우리는 임의의 작업을 수행하는 메서드를 정의할 수 있습니다.
예를 들어, GitLab 개발자들은 이중 인증에 도움을 주는 몇 가지 메서드를 추가했습니다:
def disable_two_factor!
transaction do
update(
otp_required_for_login: false,
encrypted_otp_secret: nil,
encrypted_otp_secret_iv: nil,
encrypted_otp_secret_salt: nil,
otp_grace_period_started_at: nil,
otp_backup_codes: nil
)
self.webauthn_registrations.destroy_all # rubocop: disable DestroyAll
end
end
def two_factor_enabled?
two_factor_otp_enabled? || two_factor_webauthn_enabled?
end
(참조: /opt/gitlab/embedded/service/gitlab-rails/app/models/user.rb
)
그런 다음 이러한 메서드를 모든 사용자 객체에서 사용할 수 있습니다:
user = User.find_by(username: 'root')
user.two_factor_enabled?
user.disable_two_factor!
일부 메서드는 GitLab에서 사용하는 젬 또는 Ruby 소프트웨어 패키지에 의해 정의됩니다.
예를 들어, GitLab에서 사용자 상태를 관리하기 위해 사용하는 StateMachines 젬이 있습니다:
state_machine :state, initial: :active do
event :block do
...
event :activate do
...
end
한 번 시도해 보세요:
user = User.find_by(username: 'root')
user.state
user.block
user.state
user.activate
user.state
앞서 언급했듯이, 유효성 검사 오류는 전체 객체가 데이터베이스에 저장되는 것을 방지합니다.
이로 인해 예상치 못한 상호작용이 발생할 수 있습니다:
user.password = 'password'
user.password_confirmation = 'hunter2'
user.block
false
가 반환됩니다! 이전처럼 뱅을 추가하여 무슨 일이 발생했는지 알아봅시다:
user.block!
그러면 다음과 같은 결과가 반환됩니다:
Traceback (most recent call last):
1: from (irb):87
StateMachines::InvalidTransition (Cannot transition state via :block from :active (Reason(s): Password confirmation doesn't match Password))
우리는 유효성 검사 오류가 어떻게 완전히 별개의 속성에서 돌아와 사용자 업데이트를 방해하는지를 볼 수 있습니다.
실질적으로, GitLab 관리 설정에서 이런 일이 발생하는 경우를 종종 목격합니다 –
유효성 검사는 때때로 GitLab 업데이트에서 추가되거나 변경되어 이전에 저장된 설정이 이제 유효성 검사를 통과하지 못하게 됩니다.
UI를 통해 한 번에 설정의 하위 집합만 업데이트할 수 있으므로, 이 경우 좋은 상태로 돌아가는 유일한 방법은 Rails 콘솔을 통한 직접 조작입니다.
자주 사용되는 Active Record 모델 및 객체 조회 방법
주 이메일 주소 또는 사용자 이름으로 사용자 가져오기:
User.find_by(email: 'admin@example.com')
User.find_by(username: 'root')
주 이메일 주소 또는 보조 이메일 주소로 사용자 가져오기:
User.find_by_any_email('user@example.com')
find_by_any_email
메서드는 GitLab 개발자들에 의해 추가된 사용자 정의 메서드입니다.
관리자 사용자 컬렉션 가져오기:
User.admins
admins
는 내부에서 where(admin: true)
를 수행하는 스코프 편의 메서드입니다.
경로로 프로젝트 가져오기:
Project.find_by_full_path('group/subgroup/project')
find_by_full_path
는 GitLab 개발자들에 의해 추가된 사용자 정의 메서드입니다.
숫자 ID로 프로젝트의 이슈 또는 병합 요청 가져오기:
project = Project.find_by_full_path('group/subgroup/project')
project.issues.find_by(iid: 42)
project.merge_requests.find_by(iid: 42)
iid
는 “내부 ID”를 의미하며 각 GitLab 프로젝트에 대한 이슈 및 병합 요청 ID를 스코프하는 방법입니다.
경로로 그룹 가져오기:
Group.find_by_full_path('group/subgroup')
그룹의 관련 그룹 가져오기:
group = Group.find_by_full_path('group/subgroup')
# 그룹의 부모 그룹 가져오기
group.parent
# 그룹의 자식 그룹 가져오기
group.children
그룹의 프로젝트 가져오기:
group = Group.find_by_full_path('group/subgroup')
# 그룹의 즉각적인 자식 프로젝트 가져오기
group.projects
# 하위 그룹의 프로젝트 포함해서 그룹의 자식 프로젝트 가져오기
group.all_projects
CI 파이프라인 또는 빌드 가져오기:
Ci::Pipeline.find(4151)
Ci::Build.find(66124)
파이프라인 및 작업 ID 번호는 GitLab 인스턴스 전역적으로 증가하므로, 이를 조회하기 위해 내부 ID 속성을 사용할 필요가 없습니다.
이슈나 병합 요청과는 다릅니다.
현재 애플리케이션 설정 객체 가져오기:
ApplicationSetting.current
객체를 irb
에서 열기
경고: 데이터를 변경하는 명령은 올바른 조건에서 실행되지 않으면 손상을 초래할 수 있습니다. 먼저 테스트 환경에서 명령을 실행하고 복원할 준비가 된 백업 인스턴스를 항상 준비하세요.
때때로, 객체의 컨텍스트에 있을 때 메서드를 통해 진행하는 것이 더 쉽습니다. Object
의 네임스페이스로 들어가면 어떤 객체의 컨텍스트에서 irb
를 열 수 있습니다:
Object.define_method(:irb) { binding.irb }
project = Project.last
# => #<Project id:2537 root/discard>>
project.irb
# 새로운 컨텍스트에 주목
irb(#<Project>)> web_url
# => "https://gitlab-example/root/discard"
문제 해결
Rails Runner syntax error
gitlab-rails
명령은 기본적으로 비루트 계정 및 그룹인 git:git
을 사용하여 Rails Runner를 실행합니다.
비루트 계정이 gitlab-rails runner
에 전달된 Ruby 스크립트 파일 이름을 찾을 수 없으면, 파일에 접근할 수 없다는 오류가 아닌 구문 오류가 발생할 수 있습니다.
이유 중 하나는 스크립트가 루트 계정의 홈 디렉터리에 위치하기 때문입니다.
runner
는 경로와 파일 매개 변수를 Ruby 코드로 구문 분석하려고 합니다.
예를 들어:
[root ~]# echo 'puts "hello world"' > ./helloworld.rb
[root ~]# sudo gitlab-rails runner ./helloworld.rb
Please specify a valid ruby command or the path of a script to run.
Run 'rails runner -h' for help.
/opt/gitlab/..../runner_command.rb:45: syntax error, unexpected '.'
./helloworld.rb
^
[root ~]# sudo gitlab-rails runner /root/helloworld.rb
Please specify a valid ruby command or the path of a script to run.
Run 'rails runner -h' for help.
/opt/gitlab/..../runner_command.rb:45: unknown regexp options - hllwrld
[root ~]# mv ~/helloworld.rb /tmp
[root ~]# sudo gitlab-rails runner /tmp/helloworld.rb
hello world
디렉토리에 접근할 수 있지만 파일에 접근할 수 없는 경우 유의미한 오류가 생성되어야 합니다:
[root ~]# chmod 400 /tmp/helloworld.rb
[root ~]# sudo gitlab-rails runner /tmp/helloworld.rb
Traceback (most recent call last):
[traceback removed]
/opt/gitlab/..../runner_command.rb:42:in `load': cannot load such file -- /tmp/helloworld.rb (LoadError)
이와 유사한 오류가 발생하는 경우:
[root ~]# sudo gitlab-rails runner helloworld.rb
Please specify a valid ruby command or the path of a script to run.
Run 'rails runner -h' for help.
undefined local variable or method `helloworld' for main:Object
파일을 /tmp
디렉터리로 이동시키거나 아래 예시처럼 git
사용자가 소유한 새 디렉터리를 생성하고 그 디렉터리에 스크립트를 저장할 수 있습니다:
sudo mkdir /scripts
sudo mv /script_path/helloworld.rb /scripts
sudo chown -R git:git /scripts
sudo chmod 700 /scripts
sudo gitlab-rails runner /scripts/helloworld.rb
필터링된 콘솔 출력
콘솔의 일부 출력은 특정 값, 예를 들어 변수, 로그 또는 비밀이 유출되는 것을 방지하기 위해 기본적으로 필터링될 수 있습니다. 이 출력은 [FILTERED]
로 표시됩니다. 예를 들어:
> Plan.default.actual_limits
=> ci_instance_level_variables: "[FILTERED]",
필터링을 우회하려면 객체에서 값을 직접 읽으세요. 예를 들어:
> Plan.default.limits.ci_instance_level_variables
=> 25