Внесение изменений в среду в Ruby Scripting - PullRequest
2 голосов
/ 04 апреля 2010

Вот мой сценарий

#!/usr/bin/env ruby
if __FILE__ == $0
    `cd ..` 
    puts `ls` 
end

, который работает нормально, но когда он выходит, я вернулся, где я начал. Как я могу «экспортировать» сделанные мной изменения в среду?

1 Ответ

6 голосов
/ 04 апреля 2010

Это потому, что оператор `` `не для сложных сценариев. Это полезно для запуска single команды (и чтения ее вывода). За ней нет оболочки для хранения изменений среды между его вызовами и после вашего сценария Ruby прекращается.

В системах Linux каждый процесс имеет свой собственный путь "текущего каталога" (его можно найти в / proc / ‹pid› / cwd). Изменение каталога в процессе не влияет на родительские процессы (оболочка, из которой вы запускаете программу). Если cd встроенный двоичный файл, он может изменить только свой текущий каталог, а не родительский процесс (поэтому команда cd может быть только встроенной).


Примечание

Если Ruby-скрипт должен выполняться из оболочки и должен влиять на текущий путь к каталогу оболочки, можно сделать "хитрость". Вместо того, чтобы запускать команды из самого Ruby, выведите эти команды в stdout, а затем source в оболочку, из которой вы запускали скрипт Ruby. Команды не будут выполняться отдельным процессом оболочки, поэтому все cd s будут вступать в силу в текущем экземпляре оболочки.

Итак, вместо

ruby run_commands.rb

напишите в вашем shell-скрипте что-то вроде этого:

source <(ruby prepare_and_print_commands.rb)

Shell класс

Но в Ruby есть удобный инструмент для сценариев командной строки - Shell класс! Он имеет предопределенные сокращения для часто используемых команд (таких как cd, pwd, cat, echo и т. Д.) И позволяет определять свои собственные (он поддерживает команды и псевдонимы )! Также он прозрачно поддерживает перенаправление ввода / вывода с использованием операторов |, >, <, >>, << Ruby.

Работа с Shell не требует пояснений в большинстве случаев. Взгляните на несколько простых примеров.

Создание объекта оболочки и изменение каталога

sh = Shell.new
sh.cd '~/tmp'
# or
sh = Shell.cd('~/tmp')

Работа в текущем каталоге

puts "Working directory: #{sh.pwd}"
(sh.echo 'test') | (sh.tee 'test') > STDOUT
# Redirecting possible to "left" as well as to "right".
(sh.cat < 'test') > 'triple_test'
# '>>' and '<<' are also supported.
sh.cat('test', 'test') >> 'triple_test'

(Обратите внимание, что скобки необходимы иногда из-за приоритета «перенаправления» операторов. Кроме того, вывод команды не будет выводиться на стандартный вывод по умолчанию, поэтому необходимо указать, что используется > STDOUT или > STDERR, если необходимо. )

Проверка свойств файла

puts sh.test('e', 'test')
# or
puts sh[:e, 'test']
puts sh[:exists?, 'test']
puts sh[:exists?, 'nonexistent']

(Работает аналогично функции test в обычной оболочке.)

Определение пользовательских команд и псевдонимов

#                        name    command line to execute
Shell.def_system_command 'list', 'ls -1'

#                   name   cmd   command's arguments
Shell.alias_command "lsC", "ls", "-CBF"
Shell.alias_command("lsC", "ls") { |*opts| ["-CBF", *opts] }

Имя определенной команды позже можно использовать для запуска ее точно так же, как она работает для предопределенных echo или cat, например.

Использование стека каталогов

sh.pushd '/tmp'
sh.list > STDOUT
(sh.echo sh.pwd) > STDOUT
sh.popd
sh.list > STDOUT
(sh.echo sh.pwd) > STDOUT

(Здесь используется пользовательская list команда, определенная выше.)

Кстати, есть полезная команда chdir для запуска нескольких команд в каталоге и после этого возврата в предыдущий рабочий каталог.

puts sh.pwd
sh.chdir('/tmp') do
    puts sh.pwd
end
puts sh.pwd

Пропустить объект оболочки для группы команд

# Code above, rewritten to drop out 'sh.' in front of each command.
sh.transact do
    pushd '/tmp'
    list > STDOUT
    (echo pwd) > STDOUT
    popd
    list > STDOUT
    (echo pwd) > STDOUT
end

Дополнительные функции

Дополнительно Shell имеет:

  • foreach метод для перебора строк в файле или списка файлов в каталоге (в зависимости от того, указывает ли данный путь на файл или каталог),
  • jobs и kill команды для управления процессами,
  • набор команд для работы с файлами (например, basename, chmod, chown, delete, dirname, rename, stat, symlink),
  • список File синонимов методов (directory?, executable?, exists?, readable? и т. Д.),
  • эквивалентно FileTest методам класса '(syscopy, copy, move, compare, safe_unlink, makedirs, install).
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...