Что такое код exec


Содержание

Пожалуйста, объясните функцию exec() и ее семью

Что такое функция exec() и ее семейство? Почему используется эта функция и как она работает?

Пожалуйста, кто-нибудь объяснить эти функции.

Упрощенно, в UNIX у вас есть концепция процессов и программ. Процесс — это то, в чем выполняется программа.

Простая идея UNIX «модели исполнения» заключается в том, что вы можете выполнять две операции.

Первый — это fork() , который создает совершенно новый процесс, содержащий дубликат текущей программы, включая ее состояние. Между процессами есть несколько различий, которые позволяют им выяснить, кто является родителем, а кто дочерним.

Второй — exec() , который заменяет программу в текущем процессе новой программой.

Из этих двух простых операций можно построить всю модель выполнения UNIX.

Чтобы добавить некоторые детали к вышесказанному:

Использование fork() и exec() иллюстрирует дух UNIX в том смысле, что он обеспечивает очень простой способ запуска новых процессов.

Вызов fork() создает почти дубликат текущего процесса, идентичный почти во всех отношениях (не все копируются, например, из-за ограничений ресурсов в некоторых реализациях, но идея состоит в том, чтобы создать максимально близкую копию). Один процесс вызывает fork() , в то время как два процесса возвращаются из него — звучит странно, но это действительно довольно элегантно

Новый процесс (называемый дочерним) получает другой идентификатор процесса (PID) и имеет PID старого процесса (родителя) в качестве родительского PID (PPID).

Поскольку два процесса в настоящее время работают точно в одном и том же коде, они должны быть в состоянии сказать, что есть что — код возврата fork() предоставляет эту информацию — дочерний элемент получает 0, родительский получает PID дочернего элемента (если fork() не удается, дочерний элемент не создается, а родительский код получает код ошибки). Таким образом, родительский объект знает PID дочернего элемента и может общаться с ним, уничтожать его, ждать его и т.д. (Дочерний процесс всегда может найти свой родительский процесс с помощью вызова getppid() ).

Вызов exec() заменяет все текущее содержимое процесса новой программой. Он загружает программу в текущее пространство процесса и запускает ее из точки входа.

Таким образом, fork() и exec() часто используются последовательно, чтобы запустить новую программу как дочерний элемент текущего процесса. Оболочки обычно делают это всякий раз, когда вы пытаетесь запустить такую программу, как find — оболочка разветвляется, затем потомок загружает программу find в память, настраивая все аргументы командной строки, стандартный ввод-вывод и т.д.

Но они не обязаны использоваться вместе. Для программы вполне допустимо вызывать fork() без следующего exec() , если, например, программа содержит как родительский, так и дочерний код (вам нужно быть осторожным в том, что вы делаете, у каждой реализации могут быть ограничения). Это использовалось довольно много (и все еще используется) для демонов, которые просто прослушивают порт TCP и разрабатывают свою копию для обработки определенного запроса, в то время как родитель возвращается к прослушиванию. В этой ситуации программа содержит как родительский, так и дочерний код.

Точно так же программы, которые знают, что они закончили и просто хотят запустить другую программу, не нуждаются в fork() , exec() , а затем wait()/waitpid() для ребенка. Они могут просто загрузить дочерний элемент прямо в текущее пространство процесса с помощью exec() .

Некоторые реализации UNIX имеют оптимизированный fork() , который использует то, что они называют копированием при записи. Это хитрость, чтобы отложить копирование пространства процесса в fork() до тех пор, пока программа не попытается что-то изменить в этом пространстве. это полезно для тех программ, которые используют только fork() , а не exec() , поскольку им не нужно копировать все пространство процесса. В Linux fork() только копирует таблицы страниц и новую структуру задач, exec() выполняет основную работу по «разделению» памяти двух процессов.

Если exec вызывается в соответствии с fork (и именно это происходит в основном), это вызывает запись в пространство процесса и затем копируется для дочернего процесса.

В Linux также есть vfork() , еще более оптимизированный, который разделяет практически все между двумя процессами. Из-за этого существуют определенные ограничения в том, что может делать ребенок, и родитель останавливается до тех пор, пока ребенок не вызовет exec() или _exit() .

Родитель должен быть остановлен (и дочернему не разрешено возвращаться из текущей функции), так как два процесса даже совместно используют один и тот же стек. Это немного более эффективно для классического варианта использования fork() , за которым сразу следует exec() .

Обратите внимание, что существует целое семейство вызовов exec ( execl , execle , execve и т.д.), Но exec в контексте здесь означает любой из них.

Следующая диаграмма иллюстрирует типичную операцию fork/exec , в которой оболочка bash используется для вывода каталога с помощью команды ls :

Что означает эта часть кода в exec.start?

Я прочитал код exec.Start, и там какая-то часть меня смутила. (* Cmd).stdin/out/err в [] F, что означает (* Cmd).stdXX?

Очень хорошая находка, я раньше не знал этой идиомы. Я попытаюсь сломать его. Сначала у нас есть exec.Cmd

*Cmd имеет 3 множества методов, включая stdin stdout stderr

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

Первое решение — просто скопировать/вставить код 3 раза. не приятно.

Второй — это цикл над массивом Функторов. Тип Functor будет func(c*Cmd)(f *os.File, err error) , поэтому мы объявим его как

теперь мы можем создать массив функторов. Но как выбрать метод *Cmd ? просто используя

OpenSource в заметках


Если вы частенько работаете в командной строке, вы должны быть знакомы с перенаправлением ввода/вывода. Но, возможно, вы не знакомы с перенаправлением ввода/вывода внутри bash-скрипта. Я не имею ввиду перенаправление, используемое при вызове других программ из скрипта, я говорю о перенаправлении ввода/вывода вашего скрипта в целом, начиная с момента его запуска.

Давайте, например, предположим, что вам понадобилось снабдить ваш скрипт опцией «—log», при помощи которой пользователь мог бы перенаправлять весь вывод работы вашего скрипта в нужный лог-файл. Конечно, пользователь мог бы просто перенаправить вывод скрипта средствами bash, но давайте представим, что по каким-то причинам такое решение не годится. Давайте реализуем это:

В первом утверждении if при помощи test выполняется проверка, подключён ли файловый дескриптор с номером один (поток стандартного вывода) к терминалу. Если это так, то exec «переоткрывает» его для записи в файл log. Вызов exec в контексте текущей оболочки без передачи ей команды, а только с указанием перенаправления вывода, приводит к тому, что вы можете открывать/закрывать файлы, дублируя их дескрипторы. Если же файловый дескриптор с номером 1 не подключён к терминалу, то мы просто не делаем ничего.

Если вы запустите вышеприведённый скрипт, то вы увидите, что первая и последняя echo выполнят свой вывод в терминал. Первая echo сработает потому, что она появляется до включения перенаправления, а вторая — поскольку в сценарии её вывод перенаправлен в стандартный поток ошибок (файловый дескриптор номер 2). И как же перенаправить стандартный поток ошибок в тот же файл? Всего ли одно небольшое изменение в вызове exec:

В примере выше exec перенаправляет поток ошибок туда же, куда направлен поток вывода (это, собственно, и называется дублированием файловых дескрипторов). Имейте ввиду, что порядок здесь очень важен: если вы его измените и переоткроете сперва поток ошибок (т. е. exec 2>&1 >log), то весь вывод всё равно останется направленным на терминал, поскольку он будет направлен туда же, куда и поток вывода, а тот, в свою очередь по умолчанию направлен в терминал.

Ради интереса можно попробовать выполнить то же самое, когда поток стандартного вывода не подключён к терминалу. Мы не сможем этого сделать, если поток вывода уже подключён к другому файлу или перенаправлен в конвейер, поскольку таким образом мы нарушим существовавшее перенаправление.

Возьмём, например, команду:

То, что нам нужно в конечном итоге, это эквивалент следующей команды:

Вероятно, вашей первой мыслью будет вызвать exec как-то так:

пытаясь таким образом при помощи exec перенаправить вывод в tee, запущенной в фоновом режиме. Но это не будет работать (хотя bash ничего и не скажет). Такая конструкция всего лишь перенаправляет вывод exec в tee, а поскольку exec не выводит ничего, то tee создаст пустой файл и на этом закончит.

Есть ещё одна мысль: запустить tee в фоне, направив в неё ввод из одного файлового дескриптора, а вывод перенапровить в другой. И вы можете это сделать, но проблема в том, что не существует способа создать новый процесс, стандартный ввод которого был бы подключён к каналу. Если бы мы могли это сделать, то получить вывод tee было бы просто, поскольку по умолчанию он направлен туда же, куда и вывод сценария целиком. Таким образом, мы могли бы просто закрыть поток вывода сценария и подключить его к нашему каналу, если бы была возможность этот канал создать.

Получается, мы в тупике? Нет. Решение описано в последних двух предложениях предыдущего абзаца. Нам нужно лишь создать канал, верно? Отлично, давайте использовать именованные каналы.

Здесь, если поток стандартного вывода не подключён к терминалу, мы создаём именованный канал (канал, который располагается в виде файла в файловой системе) при помощи mknod, и при помощи trap удаляем его после завершения работы сценария. Затем мы запускаем tee, связывая его поток ввода с созданным каналом и указываем выполнять запись в файл log. Помните, что tee кроме записи в файл всего полученного из потока ввода, также выводит всё в поток стандартного вывода. Также, вспомните о том, что поток вывода tee направлен туда же, куда и весь вывод сценария, вызывающего tee. Таким образом, весь вывод tee будет попадать туда, куда в данный момент направлен поток вывода нашего сценария, то есть, в перенаправленный пользователем поток вывода или канал конвейера, заданные в момент вызова сценария из командной строки. Так что теперь мы получили стандартный вывод tee там, где нам это нужно: в перенаправление или канал конвейера, определённый пользователем.

Теперь остаётся передать на вход tee нужные данные. Поскольку tee теперь считывает данные из именованного канала, всё что нам необходимо, это перенаправить стандартный вывод в именованный канал. Мы закрываем текущий поток вывода (exec 1>&- ) и открываем его в именованный канал (exec 1>$npipe). Обратите внимание, что закрытие текущего потока вывода ничего не нарушает, поскольку tee также осуществляет вывод в перенаправленный пользователем поток или канал.

Теперь, когда вы выполните команду и направите её вывод в канал к grep, вы получите и стандартный вывод и запись в лог-файле.

Подобных приёмов масса, откройте man-страницу bash!

Что такое расширение файла EXEC?

Резюме файла EXEC

Согласно нашим записям, существуют один тип(ы) файлов, связанных с расширением EXEC, самый популярный из которых отформатирован в качестве Unix Executable File. Самое распространенное связанное приложение — FreeBSD, выпущенное The FreeBSD Community. Кроме того, один различные программы позволяют вам просматривать эти файлы. Чаще всего файлы EXEC классифицируют, как Executable Files.

Файлы с расширением EXEC были идентифицированы на настольных компьютерах (и некоторых мобильных устройствах). Они полностью или частично поддерживаются FreeBSD и Linux. Рейтинг популярности данных файлов составляет «Низкий» и они обычно не используются.

Для получения дополнительной информации о файлах EXEC и связанных с ними прикладных программных средствах, см. информацию ниже. Кроме того, далее также представлено основное руководство по устранению неполадок, которое позволит вам решить проблемы, возникающие во время открытия файлов EXEC.

Популярность типов файлов
Ранг Файла
Статус файла
Страница Последнее обновление

Откройте файлы в %%os%% с помощью средства для просмотра файлов FileViewPro

Типы файлов EXEC

Ассоциация основного файла EXEC

Формат файла: .exec
Тип файла: Unix Executable File
Илон Маск рекомендует:  Odd - Функция Delphi

Unix Исполняемый файл с расширением EXEC файл представляет собой скомпилированный двоичный файл, который может быть запущен в операционной системе Unix, как Linux или FreeBSD. Файл EXEC, как расширение файла EXE для Windows. Там нет никакой конкретной программы для открытия файла EXEC, дважды щелкнув по EXEC файл приводит в запуске программы они созданы для.

Создатель: Open Source
Категория файла: Исполнимые файлы
Ключ реестра: HKEY_CLASSES_ROOT\.exec


Программные обеспечения, открывающие Unix Executable File:

Попробуйте универсальное средство для просмотра файлов

В дополнение к продуктам, перечисленным выше, мы предлагаем вам попробовать универсальное средство для просмотра файлов типа FileViewPro. Данное средство может открывать более 200 различных типов файлов, предоставляя функции редактирования для большинства из них. Скачать FileViewPro можно здесь

Поиск типов файлов

Популярность файла EXEC

Самостоятельное устранение неполадок файла любого типа

Устранение неполадок при открытии файлов EXEC

Общие проблемы с открытием файлов EXEC

FreeBSD не установлен

Дважды щелкнув по файлу EXEC вы можете увидеть системное диалоговое окно, в котором сообщается «Не удается открыть этот тип файла». В этом случае обычно это связано с тем, что на вашем компьютере не установлено FreeBSD для %%os%%. Так как ваша операционная система не знает, что делать с этим файлом, вы не сможете открыть его дважды щелкнув на него.

Совет: Если вам извстна другая программа, которая может открыть файл EXEC, вы можете попробовать открыть данный файл, выбрав это приложение из списка возможных программ.

Установлена неправильная версия FreeBSD

В некоторых случаях у вас может быть более новая (или более старая) версия файла Unix Executable File, не поддерживаемая установленной версией приложения. При отсутствии правильной версии ПО FreeBSD (или любой из других программ, перечисленных выше), может потребоваться загрузить другую версию ПО или одного из других прикладных программных средств, перечисленных выше. Такая проблема чаще всего возникает при работе в более старой версии прикладного программного средства с файлом, созданным в более новой версии, который старая версия не может распознать.

Совет: Иногда вы можете получить общее представление о версии файла EXEC, щелкнув правой кнопкой мыши на файл, а затем выбрав «Свойства» (Windows) или «Получить информацию» (Mac OSX).

Резюме: В любом случае, большинство проблем, возникающих во время открытия файлов EXEC, связаны с отсутствием на вашем компьютере установленного правильного прикладного программного средства.

Другие причины проблем с открытием файлов EXEC

Даже если на вашем компьютере уже установлено FreeBSD или другое программное обеспечение, связанное с EXEC, вы все равно можете столкнуться с проблемами во время открытия файлов Unix Executable File. Если проблемы открытия файлов EXEC до сих пор не устранены, возможно, причина кроется в других проблемах, не позволяющих открыть эти файлы. Такие проблемы включают (представлены в порядке от наиболее до наименее распространенных):

  • Неверные ссылки на файлы EXEC в реестре Windows («телефонная книга» операционной системы Windows)
  • Случайное удаление описания файла EXEC в реестре Windows
  • Неполная или неправильная установка прикладного программного средства, связанного с форматом EXEC
  • Повреждение файла EXEC (проблемы с самим файлом Unix Executable File )
  • Заражение EXEC вредоносным ПО
  • Повреждены или устарелидрайверы устройств оборудования, связанного с файлом EXEC
  • Отсутствие на компьютере достаточных системных ресурсов для открытия формата Unix Executable File

Функции _exec, _wexec _exec, _wexec Functions

Каждая функция в этом семействе загружает и выполняет новый процесс. Each function in this family loads and executes a new process:

Буква в конце имени функции определяет вариацию. The letter at the end of the function name determines the variation.

Суффикс функции _exec _exec function suffix ОПИСАНИЕ Description
e envp , массив указателей на параметры среды, передается в новый процесс. envp , array of pointers to environment settings, is passed to the new process.
l Аргументы командной строки передаются по отдельности в функцию _exec . Command-line arguments are passed individually to _exec function. Обычно используется, когда число параметров нового процесса известно заранее. Typically used when the number of parameters to the new process is known in advance.
p Переменная среды PATH используется для поиска файла для выполнения. PATH environment variable is used to find the file to execute.
v argv , массив указателей на аргументы командной строки, передается в _exec . argv , array of pointers to command-line arguments, is passed to _exec . Обычно используется, когда число параметров нового процесса непостоянно. Typically used when the number of parameters to the new process is variable.

Примечания Remarks

Каждая функция _exec загружает и выполняет новый процесс. Each _exec function loads and executes a new process. Все функции _exec используют одну и ту же функцию операционной системы (CreateProcess). All _exec functions use the same operating-system function (CreateProcess). Функции _exec автоматически обрабатывают аргументы строки многобайтовых символов соответствующим образом, распознавая последовательности многобайтовых символов согласно многобайтовой кодовой странице, используемой в данный момент. The _exec functions automatically handle multibyte-character string arguments as appropriate, recognizing multibyte-character sequences according to the multibyte code page currently in use. Функции _wexec — это версии функций _exec с расширенными символами. The _wexec functions are wide-character versions of the _exec functions. Поведение функций _wexec идентично их аналогам из семейства _exec за исключением того, что они не обрабатывают строки многобайтовых символов. The _wexec functions behave identically to their _exec family counterparts except that they do not handle multibyte-character strings.

Сопоставления подпрограмм обработки обычного текста Generic-Text Routine Mappings

Процедура Tchar.h Tchar.h routine _UNICODE и _MBCS не определены _UNICODE and _MBCS not defined _MBCS определено _MBCS defined _UNICODE определено _UNICODE defined
_texecl _execl _execl _wexecl
_texecle _execle _execle _wexecle
_texeclp _execlp _execlp _wexeclp
_texeclpe _execlpe _execlpe _wexeclpe
_texecv _execv _execv _wexecv
_texecve _execve _execve _wexecve
_texecvp _execvp _execvp _wexecvp
_texecvpe _execvpe _execvpe _wexecvpe

Параметр cmdname указывает файл, который будет выполняться как новый процесс. The cmdname parameter specifies the file to be executed as the new process. Он может указывать полный путь (от корневого каталога), частичный путь (от текущего рабочего каталога) или имя файла. It can specify a full path (from the root), a partial path (from the current working directory), or a file name. Если cmdname не указывает расширение файла или не заканчивается точкой (.), функция _exec выполняет поиск названного файла. If cmdname does not have a file name extension or does not end with a period (.), the _exec function searches for the named file. Если поиск не дает результатов, функция пытается найти то же основное имя с расширением COM, а затем с расширениями EXE, BAT и CMD. If the search is unsuccessful, it tries the same base name with the .com file name extension and then with the .exe, .bat, and .cmd file name extensions. Если параметр cmdname включает расширение файла, для поиска используется только это расширение. If cmdname has a file name extension, only that extension is used in the search. Если cmdname заканчивается точкой, функция _exec выполняет поиск cmdname без расширения файла. If cmdname ends with a period, the _exec function searches for cmdname with no file name extension. _execlp , _execlpe , _execvp и _execvpe выполняют поиск cmdname (используя те же процедуры) в каталогах, указанных переменной среды PATH . _execlp , _execlpe , _execvp , and _execvpe search for cmdname (using the same procedures) in the directories specified by the PATH environment variable. Если cmdname содержит описатель диска или любые косые черты (то есть является относительным путем), функция _exec выполняет поиск только указанного файла, а не пути. If cmdname contains a drive specifier or any slashes (that is, if it is a relative path), the _exec call searches only for the specified file; the path is not searched.

Параметры передаются в новый процесс путем предоставления одного или нескольких указателей на строки символов как параметров в вызове _exec . Parameters are passed to the new process by giving one or more pointers to character strings as parameters in the _exec call. Эти строки символов формируют список параметров для нового процесса. These character strings form the parameter list for the new process. Общая длина наследуемых параметров среды и строк, формирующих список параметров для нового процесса, не должна превышать 32 КБ. The combined length of the inherited environment settings and the strings forming the parameter list for the new process must not exceed 32 kilobytes. Символ null, завершающий строку (‘\0’), для каждой строки не учитывается, однако учитываются символы пробелов (вставляемые автоматически для разделения параметров). The terminating null character (‘\0’) for each string is not included in the count, but space characters (inserted automatically to separate the parameters) are counted.

Пробелы, встроенные в строки, могут вызывать непредвиденное поведение. Например, если передать в функцию _exec строку «hi there» , это приведет к тому, что новый процесс получит два аргумента: «hi» и «there» . Spaces embedded in strings may cause unexpected behavior; for example, passing _exec the string «hi there» will result in the new process getting two arguments, «hi» and «there» . Если предполагалось, что новый процесс должен открыть файл с именем hi there, произойдет сбой процесса. If the intent was to have the new process open a file named «hi there», the process would fail. Этого можно избежать, заключив строку в кавычки: «\»hi there\»» . You can avoid this by quoting the string: «\»hi there\»» .

Не передавайте данные, вводимые пользователем, в функцию _exec , не выбрав это содержимое явно. Do not pass user input to _exec without explicitly checking its content. _exec вызывает функцию CreateProcess, поэтому имейте в виду, что неполные пути могут привести к потенциальным уязвимостям безопасности. _exec will result in a call to CreateProcess so keep in mind that unqualified path names could lead to potential security vulnerabilities.

Эти функции _exec проверяют свои параметры. The _exec functions validate their parameters. Если ожидаемые параметры являются пустыми указателями или строками либо они пропущены, функции _exec вызывают обработчик недопустимых параметров, как описано в разделе Проверка параметров. If expected parameters are null pointers, empty strings, or omitted, the _exec functions invoke the invalid parameter handler as described in Parameter Validation. Если продолжение выполнения разрешено, эти функции устанавливают для errno значение EINVAL и возвращают -1. If execution is allowed to continue, these functions set errno to EINVAL and return -1. Новые процессы не выполняются. No new process is executed.


Указатели аргументов могут передаваться как отдельные параметры (в _execl , _execle , _execlp и _execlpe ) или как массивы указателей (в _execv , _execve , _execvp и _execvpe ). The argument pointers can be passed as separate parameters (in _execl , _execle , _execlp , and _execlpe ) or as an array of pointers (in _execv , _execve , _execvp , and _execvpe ). По крайней мере один параметр, arg0 , должен быть передан в новый процесс; этот параметр — argv [0] нового процесса. At least one parameter, arg0 , must be passed to the new process; this parameter is argv [0] of the new process. Обычно этот параметр является копией cmdname Usually, this parameter is a copy of cmdname . (другое значение не создает ошибку). (A different value does not produce an error.)

Вызовы функций _execl , _execle , _execlp и _execlpe обычно используются, когда число параметров известно заранее. The _execl , _execle , _execlp , and _execlpe calls are typically used when the number of parameters is known in advance. Параметр arg0 , как правило, является указателем на cmdname . The parameter arg0 is usually a pointer to cmdname . Параметры с arg1 по argn указывают на строку символов, формирующую новый список параметров. The parameters arg1 through argn point to the character strings forming the new parameter list. За параметром argn должен следовать пустой указатель, отмечающий конец списка параметров. A null pointer must follow argn to mark the end of the parameter list.

Функции _execv , _execve , _execvp и _execvpe можно вызывать, когда число параметров в новом процессе не определено. The _execv , _execve , _execvp , and _execvpe calls are useful when the number of parameters to the new process is variable. Указатели на параметры передаются как массив, argv . Pointers to the parameters are passed as an array, argv . Параметр argv [0] обычно является указателем на cmdname . The parameter argv [0] is usually a pointer to cmdname . Параметры с argv [1] по argv [ n ] указывают на строки символов, формирующие новый список параметров. The parameters argv [1] through argv [ n ] point to the character strings forming the new parameter list. Параметр argv [ n +1] должен быть указателем на NULL, отмечающим конец списка параметров. The parameter argv [ n +1] must be a NULL pointer to mark the end of the parameter list.

Файлы, открытые во время вызова функции _exec , остаются открытыми в новом процессе. Files that are open when an _exec call is made remain open in the new process. В вызовах _execl , _execlp , _execv и _execvp новый процесс наследует среду вызывающего процесса. In _execl , _execlp , _execv , and _execvp calls, the new process inherits the environment of the calling process. Вызовы функций _execle , _execlpe , _execve и _execvpe изменяют среду для нового процесса, передавая список параметров среды с помощью параметра envp . _execle , _execlpe , _execve , and _execvpe calls alter the environment for the new process by passing a list of environment settings through the envp parameter. envp — это массив указателей символов, каждый элемент которого (за исключением последнего) указывает на строку, завершающуюся символом null, определенную в переменной среды. envp is an array of character pointers, each element of which (except for the final element) points to a null-terminated string defining an environment variable. Такие строки обычно имеют вид NAME = value , где NAME — это имя переменной среды, а value — строковое значение, задаваемое для данной переменной. Such a string usually has the form NAME = value where NAME is the name of an environment variable and value is the string value to which that variable is set. (Учтите, что value не заключается в двойные кавычки.) Последним элементом массива envp должен быть NULL. (Note that value is not enclosed in double quotation marks.) The final element of the envp array should be NULL. Если же значение самого параметра envp — NULL, новый процесс наследует параметры среды вызывающего процесса. When envp itself is NULL, the new process inherits the environment settings of the calling process.

Программа, выполняемая с одной из функций _exec , всегда загружается в память, как если бы для поля максимального объема выделяемой памяти в заголовке EXE-файла было задано значение по умолчанию 0xFFFFH. A program executed with one of the _exec functions is always loaded into memory as if the maximum allocation field in the program’s .exe file header were set to the default value of 0xFFFFH.

Вызовы _exec не сохраняют режимы преобразования открытых файлов. The _exec calls do not preserve the translation modes of open files. Если новый процесс должен использовать файлы, наследуемые из вызывающего процесса, используйте подпрограмму _setmode, чтобы задать нужный режим преобразования для этих файлов. If the new process must use files inherited from the calling process, use the _setmode routine to set the translation mode of these files to the desired mode. Перед вызовом функции fflush необходимо явно сбросить (используя ключевое слово _flushall или _exec ) или закрыть все потоки. You must explicitly flush (using fflush or _flushall ) or close any stream before the _exec function call. Сигнальные параметры не сохраняются в новых процессах, создаваемых вызовом подпрограмм _exec . Signal settings are not preserved in new processes that are created by calls to _exec routines. Сигнальные параметры сбрасываются до значений по умолчанию в новом процессе. The signal settings are reset to the default in the new process.

exec — Исполняет внешнюю программу

(PHP 4, PHP 5, PHP 7)

exec — Исполняет внешнюю программу

Описание

exec() исполняет команду command .

Список параметров

Команда (имя программы с аргументами — прим.пер.), которая будет исполнена.

Если параметр output указан, то массив будет заполнен строками вывода программы. Завершающие пробелы, такие как \n (перевод строки — прим.пер.), включены в массив не будут. Обратите внимание, что если массив уже содержит какие-либо элементы перед вызовом функции exec() , то вывод команды будет дописан в конец массива. Если же вы не хотите дополнять предыдущее содержимое массива, следует вызвать функцию unset() с именем массива в качестве аргумента перед его передачей в качестве аргумента функции exec() .

Если заданы оба параметра return_var и output , то при выходе эта переменная будет содержать статус завершения внешней программы.

Возвращаемые значения

Последняя строка вывода при исполнении заданной команды. Если требуется исполнить команду и получить все данные программы обратно без какой-либо обработки, следует использовать функцию passthru() .

Для получения вывода исполняемой программы, убедитесь, что параметр output инициализирован и используется.

Примеры

Пример #1 Пример функции exec()

Примечания

Если вы собираетесь передавать функции пользовательские данные, используйте функции escapeshellarg() или escapeshellcmd() для того, чтобы пользователи не смогли обмануть систему, запустив произвольную команду.

Если вы собираетесь использовать эту функцию в программе, работающей в качестве демона, убедитесь, что стандартный вывод функции направлен в файл или другой поток, в противном случае PHP зависнет вплоть до конца выполнения программы.

Замечание: В случае работы в безопасном режиме, вы можете запускать что-либо только в пределах safe_mode_exec_dir. В настоящее время по практическим причинам запрещено использование .. в качестве компонента пути к исполняемому файлу.

В случае работы в безопасном режиме, строка с командой экранируется с помощью escapeshellcmd() . Таким образом echo y | echo x становится echo y \| echo x.

Смотрите также

  • system() — Выполняет внешнюю программу и отображает её вывод
  • passthru() — Выполняет внешнюю программу и отображает необработанный вывод
  • escapeshellcmd() — Экранирует метасимволы командной строки
  • pcntl_exec() — Executes specified program in current process space
  • backtick operator

Чем может быть полезен динамический SQL

В наших проектах нам приходится решать различные задачи. Для решения некоторых из них мы используем dynamic T-Sql (далее по тексту dynamic sql).

Для чего нужен dynamic sql? Каждый решает для себя. В одном из проектов с помощью dynamic sql мы решили задачи построения динамичных отчетов, в других — миграцию данных. Также dynamic sql незаменим в случаях, когда требуется создать/изменить/получить данные или объекты, но значения/названия приходят в качестве параметров. Да, это может показаться абсурдом, но есть и такие задачи.
Дальше мы покажем несколько примеров, как это можно реализовать с помощью dynamic sql.


Выполнить динамическую команду можно несколькими способами:

  • С использование ключевого слова EXEC/EXECUTE ;
  • C использование хранимой процедуры sp_executesql

Данные способы отличаются между собой кардинально. На небольшом примере мы постараемся пояснить, чем они отличаются.

Пример кода с EXEC/EXECUTE:

Как видно из запроса выше, мы формируем динамическую команду. Если выполнить select @sql , то результат будет следующий:

Что же тут плохого? — Запрос отработает, и все будут довольны. Но все же, есть несколько причин, почему так делать не стоит:

  1. При написании команды очень легко ошибиться с количеством «’», т.к. необходимо указывать дополнительные «’», чтобы передать текстовое значение в запрос.
  2. При таком запросе возможны Sql инъекции (SQL Injection). Например, стоит задать значение для @city вроде такого

Что изменится при использовании sp_executesql ? – Разработчику проще писать код и его отлаживать, т.к. код будет написан практически как обычный Sql запрос.

Пример кода с sp_executesql:

Что же изменилось?

  1. В отличие от EXECUTE при использовании sp_executesql , не нужно никакое приведение типов, если мы используем типизированные параметры sp_executesql.
  2. Это решает проблему с дополнительными «’».
  3. Решается проблема безопасности — Sql инъекции (SQL Injection).

Для обоих подходов планы запросов кэшируются, но они отличаются. Эти отличия приведены на рисунке 1 и рисунке 2.

Получение плана запроса:

План запроса при использовании EXEC:

План запроса при использовании sp_executesql:

Также одно из преимуществ использования sp_executesql – это возможность возвращать значение через OUT параметр.

Далее приведем пример, как мы решили одну из проблем в проекте с использованием dynamic sql.

Допустим, у нас есть товар (да неважно, собственно, что это: товар, анкета на должность, персональная анкета). Смысл в том, что каждый объект имеет свой набор свойств (атрибутов), который его характеризует, а их может быть разное количество, и они будут разного типа. Как хранить в БД – это проблема архитектуры.

Для клиента нужен был отчет, который из себя представлял n строк на m столбцов. Где m и был наш набор атрибутов. Отчет собирался по группе объектов или для какого-то объекта из группы. Но смысл остается все тот же: каждый отчет содержит разное количество столбцов для каждой группы объектов.

Поскольку изначально существовала связь между объектами, то решение проблемы выбрали без изменения архитектуры БД. На наш взгляд, решений данной проблемы может быть несколько:

  • Использовать систему отчетности, например, MS Sql Reporting Service. Создать матричный отчет, а в качестве запроса у нас будет «простой» Select . Почему мы так не сделали? В проекте не так много было отчетов, чтобы внедрять туда SSRS.
  • Использовать тот же «простой» select и на серверной стороне уже создавать DataSet необходимой «формы». Да, так задача была решена изначально, когда данных о товарах было очень мало. Как только данных стало достаточно много, то время сбора отчета стало выходит за установленный timeout.
  • Использовать Pivot в sql. Да, отличное решение, когда вы знаете, что у вас только эти атрибуты, и новых не будет. А что делать, когда количество атрибутов часто меняется. И опять же, для каждой группы объектов у нас свой набор атрибутов, мы снова вернемся к созданию процедуры для каждой группы объектов. Не очень удобное решение, не правда ли?
  • А если использовать Pivot, но добавить туда немного dynamic sql? – Да, это решение, которое имеет право на жизнь. Его мы и опишем, как пример использования dynamic sql…

В основе отчета будет лежать обычный запрос:

Что такое код exec

временем родительский процесс приостанавливает свое выполнение посредством вызова функции waitpid. После завершения порожденного процесса выполнение родительского возобновляется, и его переменным status и child pid присваивается код завершения порожденного процесса, а также его идентификатор. Родительский процесс использует макросы, определенные в , для определения статуса выполнения порожаенного процесса следуюшим способом:

Если WIFEXITED возврашает ненулевое значение, это означает, что порожденный процесс был завершен с использованием вызова exit. Родительский процесс извлекает его код завершения (который в этом примере равен 15) с помошью макрокоманды WEXITSTATUS. Затем он направляет полученное значение в стандартный поток ошибок.

Если WIFEXITED возврашает нулевое значение, а WIFSTOPPED — ненулевое, то порожденный процесс был остановлен сигналом. Родительский процесс извлекает номер сигнала посредством макрокоманды WSTOPSIG и направляет это значение в стандартный поток ошибок.

Если и WIFEXITED, и WIFSTOPPED возвращают нулевое, а WIFSIG-NALED — ненулевое значение, то порожденный процесс был завершен неперехваченным сигналом. Родительский процесс извлекает номер сигнала с помошью макрокоманды WTERMSIG и направляет это значение в стандартный поток ошибок.

Если WIFEXITED, WIFSTOPPED и WIFSIGNALED возвращают нулевые значения, это означает, что либо родительский процесс не имеет порожденных, либо вызов waitpid был прерван сигналом. Поэтому родительский процесс вызывает функцию perror для вывода подробной диагностической информации о причинах неудачи.


Результаты выполнения этой программы могут быть такими:

% СС -о test waitpid test waitpid.C

Parent process after fork

Child process created

8.2.4. Функция exec

Системный вызов exec заставляет вызывающий процесс изменить свой контекст и выполнить другую программу. Есть шесть версий системного вызова exec. Все они выполняют одну и ту же функцию, но отличаются друг От друга аргументами.

Вот Прототипы функций exec;

int exec/ (const char* path, const char* arg, . );

int exec/e (const char* path, const char* arg, const char** env);

int execv (const char* path, const char** argv, . );

int exectp (const char* file, const char** argv, . );

int execve (const char* path, const char** argv, const char** env);

Первый аргумент функции является либо полным путевым именем, либо именем файла программы, подлежащей исполнению. Если вызов проходит успешно, данные и команды вызывающего процесса, хранящиеся в памяти, перекрываются данными и командами новой программы. Процесс начинает выполнение новой программы с ее первых строк. После завершения выполнения новой программы код завершения процесса передается обратно родительскому процессу. Следует обратить внимание, что в отличие от fork, создающей порожденный процесс, который выполняется независимо от родительского, exec лишь изменяет содержание вызывающего процесса для выполнения другой программы.

Вызов exec может быть неудачным, если к программе, подлежащей выполнению, нет доступа или если она не имеет разрешения на вьшолнение. Далее, программа, указанная в первом аргументе вызова exec, должна быть исполняемым файлом (имеющим, например, формат a.out). В UNIX, однако, можно указать имя сценария shell для вызовов execlp и execvp, чтобы я ipo UNIX для интерпретации сценария shell активизировало Bourne-shell i/bin/sh). Так как в POSIX. 1 shell не определен, применение execlp или execvp для выполнения сценариев shell не допустимо. В действительности это не является проблемой, так как пользователи всегда могут активизировать —hell вызовом exec, указав при этом имя того сценария, который требуется выполнить.

Суффикс р в вызовах execlp и execvp указывает, что если фактическое значение аргумента fde не начинается с / , то функции при поиске подлежащего выполнению файла будут использовать переменную среды PATH. Для всех остальных функций exec фактическим значением их первого аргумента должно быть путевое имя файла, подлежащего выполнению.

Аргументы arg и argv являются аргументами также для программы, вызванной функцией exec. Они отображаются в переменную argv функции main новой программы. Для функций execl, execlp и execle аргумент arg Отображается в argvfOJ, значение, указанное после arg,- в argvflj и т.д. Список аргументов, имеющийся в вызове exec, должен завершиться значением NULL, чтобы указать функции, где необходимо прекратить поиск значений аргумента. Для функций execv, execvp и execve аргумент argv является массивом (вектором) указателей на символьные строки, где каждая

строка представляет собой одно значение аргумента. Аргумент argv отображается непосредственно в переменную argv функции main новой программы. Так, символ / в имени функции exec указывает на то, что значения аргумента передаются в виде списка, а символ v в этом имени означает, что аргументы передаются в векторном формате.

Следует заметить, что в каждом вызове exec необходимо указывать по крайней мере два значения аргументов. Первое значение (arg или argv[0]) — это имя программы, подлежащей выполнению; оно отображается в argvfOJ функции main новой программы. Второй обязательный аргумент — значение NULL, заверщающее список аргументов (для execl, execlp и execle) либо вектор аргументов (для execv, execvp и execve).

Последний элемент env должен быть NULL, что сигнализирует об окончании списка. В среде, отличной от ANSI С, значение env будет присвоено третьему параметру функции main выполняемой программы. В среде ANSI С функция main может иметь только два аргумента

Если вызов exec успещен, сегменты стека, данных и текста первоначального процесса заменяются новыми сегментами, относящимися к выполняемой программе. Однако таблица дескрипторов файлов процесса остается неизменной. Те из файловых дескрипторов, чьи флаги close-on-exec были установлены (системным вызовом fcntl), будут закрыты перед выполнением новой программы. Во время выполнения программы с помощью API exec возможны следующие изменения атрибутов процесса:

Эффективный идентификатор пользователя: изменяется, если для выполняемой программы установлен бит смены идентификатора пользователя set-UID.

Эффективный идентификатор группы: изменяется, если для выполняемой программы установлен бит смены идентификатора группы set-GID.

Установленный идентификатор пользователя: изменяется, если для выполняемой программы установлен set-UID.

Параметры обработки сигналов: для сигналов, определенных в процессе как перехватываемые, устанавливается режим обработки по умолчанию, когда процесс начинает выполнение новой программы. Определяемые пользователем функции-обработчики сигналов в выполняемой программе отсутствуют.

Большинство программ вызывают exec в порожденном процессе, так как выполнение родительского процесса после вызова exec желательно продолжать. Однако вызовы fork и exec реализуются в качестве двух раздельных функций. Это происходит по следующим причинам:

Реализовать/ог/: и exec раздельно проще.

Программа может вызвать exec без fork, а fork без exec. Это обеспечивает гибкость в использовании этих функций.

Многие программы будут производить определенные операции в порожденных процессах, например такие, как переназначение стандартного ввода-вывода в файлы перед вызовом exec. Это становится возможным благодаря разделению API fork и exec.

Exec — Выполнение кода, консоль запросов и не только!

Это облегченный частичный аналог ИР_мобильного. Меньше тормозов, но и функционала меньше.

Описание (также включено в саму обработку):

Представляем Вашему вниманию обработку Exec, предназначенную для быстрого выполнения определенных операций в базе данных 1С, а также для многого другого.


Exec, features:

— СтруктураПараметров. Произвольный. Используется для хранения параметров текущего окна исполнения.

— СтруктураСтрокиСоединения. Произвольный. Используется для хранения строки соединения ADODB.

«Страница исполнения» (доступна в управляемом режиме)

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

— Окно редактирования исполняемого кода со следующими доп. возможностями:

  • Добавление/удаление страниц исполнения (страницы и их параметры сохраняются при закрытии обработки).
  • Простой «интеллисенс» (вызывается по Ctrl+Пробел). Умеет:

o Определять тип переменных, включая работу через точку, используя вставленный в обработку «справочник типов», представляющий собой кучу макетов, по одному на каждый тип значения (в том числе существует макет, содержащий служебные процедуры, функции и переменные локального контекста этой обработки).

o Получать список реквизитов, общих реквизитов, стандартных реквизитов, табличных частей, стандартных табличных частей, измерений, ресурсов.

НЕ умеет, и не будет уметь:

o Получать функции/процедуры общих модулей, объектов и менеджеров объектов.

Пока что НЕ умеет, но будет уметь:

o Получать реквизиты табличных частей.

o Получать список типов в предложении «Новый».

  • Замер производительности (в миллисекундах):

o Для начала замера необходимо вставить в код вызов процедуры «НачатьЗамерПроизводительности();». Данная функция возвращает новый уровень замера. Уровни замеров начинаются с 0.

o Для завершения замера необходимо вызвать функцию «ЗавершитьЗамерПроизводительности(бСообщитьВремя = Ложь);». Если передать в параметре функции «Истина», то функция самостоятельно выдаст сообщение пользователю о завершении замера. Можно производить вложенные замеры. Уровень вложенности не ограничен. Функция возвращает массив, где первым значением идет время замера, вторым — отформатированное время замера строкой, а третьим — уровень замера.

o Также существует возможность выполнения запросов в коде (на странице исполнения кода) с замером производительности запроса как в консоли запросов. Фактически, это возможность выполнить запрос из кода так, как будто он выполнен на странице консоли запросов. Для этого необходимо вызвать процедуру ВыполнитьЗапросСЗамеромПоВТ(Запрос). Для работы с результатом запроса в этом случае можно использовать переменную МассивИменноРезультатовЗапроса.

  • Простейший функционал обработки ожидания. Работает так:

o есть процедура ВыполнитьКодОбработчикОжидания(); она вызывает «как бы» нажатие кнопки «Выполнить» на странице исполнения кода; но перед этим она вставляет в структуру параметров свойство «бВыполняетсяВОбработчикеОжидания»; сама процедура выполнения кода, если находит это свойство в структуре параметров, удаляет его оттуда. Таким образом, можно выполнить примерно такой код:

Он, фактически, означает, что через 3 секунды и каждые три последующих будет выведено сообщение «Ура!». Если, конечно, не переключаться на другие страницы панели исполнения кода.

Сделан функционал для того, чтобы можно было запускать некие «Периодические» действия в рабочей базе без использования регламентных заданий и не в бесконечном цикле (например, очень жестко зависло регламентное задание и сервер перезагружать нельзя, а его функционал архиважен для работы).

В дальнейшем, данный функционал планируется совершенствовать (например, отвязать его от текущей страницы панели исполнения кода).

— Таблица используемых параметров (просмотр, перетаскивание в окно редактирования, изменение имени параметра)

— Командная панель, которая содержит:

  • кнопку сохранения параметров и текста в файл с расширением «|*.exec» (Ctrl+S)
  • кнопку загрузки параметров и текста из файла с расширением «|*.exec» (Ctrl+O)
  • кнопку вызова формы редактирования параметров
  • кнопку управления видимостью таблицы параметров
  • кнопку помещения в исполняемый код имен таблицы/дерева результата запроса или массива таблиц результатов пакета
  • (атавизм, возможно, в будущих версиях обработки будет исключено — или переделано в кнопку открытия списка свойств
  • и методов контекста обработки)

— Форма редактирования параметров.


  • Форма предназначена для редактирования параметров которые впоследствие можно использовать в исполняемом коде.

Например задав параметр «СсылкаДокумента» и выбрав конкретную ссылку на документ,

в исполняемом коде становится доступна переменная СсылкаДокумента содержащая выранное значение.

На имя параметра наложено ограничение ключа структуры.

«Страница изменения» (доступна в управляемом режиме)

Страница предназначена для выбора объекта из базы данных и просмотра (редактирования) его свойств.
Функционал:

— Поле выбора изменяемого объекта

— Поле отображения идентификатора изменяемого объекта

— Кнопка копирования идентификатора изменяемого объекта в буфер

— Возможность открытия произвольной формы объекта изменения

— Дерево имен и значений реквизитов выбранного объекта (с возможностью изменения или очистки)

— Кнопки изменения состава строк табличных частей выбранного объекта

— Кнопки изменения порядка следования строк табличных частей выбранного объекта

— Кнопки пометки на удаление и непосредственного удаления объекта

«Страница консоли запросов»

Страница предназначена для выполнения запросов к базе используя встроенный язык запросов.
Функционал:

— Командную панель, которая содержит:

  • кнопка сохранения дерева запросов в файл с расширением «|*.exsel» (Ctrl+S)
  • кнопка загрузки дерева запросов из файла с расширением «|*.exsel» (Ctrl+O)
  • кнопка редактирования параметров запроса
  • кнопка экспорта текста запроса в буфер обмена (подставляются двойные кавычки и символы переноса строки)
  • кнопка вставки текста запроса из буфера обмена (убираются двойные кавычки и символы переноса строки)

— Окно редактирования запроса на встроенном языке, с возможностью использования конструктора запросов

— Таблица результата исполнения запроса в виде таблицы, дерева или сводной таблицы.

Доступны как переменные «ТаблицаРезультатаЗапроса», «ДеревоРезультатаЗапроса» и «СводнаяТаблицаЗапроса» соответственно в окне исполнения.

— Все результаты выполнения пакетного запроса в виде списка временных таблиц с именами.

Доступны как массив, содержащий таблицы в порядке их следования в запросе. Имя массива: МассивВременныхТаблицЗапроса.

«Страница запросов SQL»

Страница предназначена для выполнения прямых запросов к SQL базам используя ADODB.
Функционал:

— Строка соединения (редактируется в специальном окне)

— Командную панель, которая содержит:

  • кнопка сохранения строки соединения и текста запроса в файл с расширением «|*.exsql» (Ctrl+S)
  • кнопка загрузки строки соединения и текста запроса из файла с расширением «|*.exsql» (Ctrl+O)


— Окно редактирования запроса к SQL

— Таблица результата исполнения запроса к SQL.

Доступна как переменная «ТаблицаРезультатаSQL» в окне исполнения.

«Соответствие имен объектов с SQL»

Страница предназначена для получения соответствий имен объектов метаданных с именами таблиц и полей хранения этих объектов в SQL.

«Страница обмена данными» (доступна в управляемом режиме)

Страница предназначена для выполнения выгрузки (загрузки) данных между идентичными конфигурациями.
Функционал:

— Поля выбора типа и вида объекта для выгрузки (загрузки)

— Поле выбора имени файла обмена

В планах дальнейшей разработки:

— Перевод страниц в управляемый режим:

«Страница запросов (© consquery8.*)»

«Страница прямых запросов к SQL»

«Соответствие имен объектов с SQL»

— Унифицированная работа с параметрами (для страниц исполнения и запросов)

— Доступ к описанию внутренних переменных в режиме предприятия

«Страница прямых запросов к SQL»

— возможность просмотра внутренней структуры хранения данных 1С (только для базы MS SQL Server)

— конвертация имен метаданных в имена таблиц хранения данных 1С (только для базы MS SQL Server)

«Страница обмена данными»

— возможность настраиваемой выгрузки объекта по набору свойств (для каждого свойства возможна установка правила выгрузки значения, правила выгружаются в отдельный файл)

— возможность настраиваемой загрузки объекта по набору свойств (для каждого свойства возможна установка правила загрузки значения, правила загружаются из отдельного файла)

— возможность указания списка объектов для выгрузки

Что такое окружающая среда, когда EXEC код ядра

для x86, ядро ​​загружается биос на 0x7c00 и Exec там. Я не знаком с изображением ядра и запутанным в среде, когда Exec на 0x7c00. Я недавно rearch формата ELF и знаю, что есть много секторов в загружаемом файл, ЛД загрузить файл ELF и инициализировать процедуру, когда состояние происходит EXEC. Но для загрузки случае ядра, что случилось?

Прежде всего, ядро ​​не загружается в 0x7c00 по BIOS или прошивку, но «Загрузчик» загружен там. В системах x86 / IA32, исходная среда программного обеспечения системы является 16-битным режимом (так называемый реальным режимом собственно). В реальном режиме, чтобы получить доступ к памяти, код использует сегмент: систему адресации памяти смещения. Это позволяет линейные адреса больше, чем 16-битного размера, которые будут использоваться.

BIOS не имеет ни малейшего представления о файловой системе для загрузчика. Только 512 байт, из загрузочного сектора диска, загружаются и копируются по адресу 0x7c00. Код должен быть готов выполнить там без переездов / связи, поскольку BIOS не знает ничего из этого. Кроме того, запись для загрузчика должны быть 0x7c00 только, и, таким образом ELF-файлов (которые содержат заголовок в самом запуске) не может быть загружен, потому что код не находится в начальной. Так, загрузчик в виде исходного двоичного файла.

BIOS предоставляет услуги с использованием устройств в системе с помощью

инструкция, которые эти 512 байт загружены должны использовать для погрузчика других секторов на диске. Это задача очень низкого уровня, который может быть очень плохо. Программирование в пользовательском пространстве очень легко по сравнению с здесь.

Обратите внимание, что Загрузчик-файл может быть любого размера, но первые 512-байты будут загружены BIOS. Таким образом, этот код будет загружать другие сектора на диске.

Ядро Загрузка загрузчика:

Загрузчик расстановок системы для использования ядра. Advanced загрузчики как GRUB, можно даже загрузить ELF-файлы и прочитать обычные файловые системы (например, FAT). Таким образом, ядро ​​получает гораздо более высокий уровень, чем среду загрузчика. Некоторые погрузчики, как GRUB2 позволяют загрузку других ядра-модули и настройки защищенного режима для ядра.

Илон Маск рекомендует:  Скрипт ajax комментариев скачивание и установка
Понравилась статья? Поделиться с друзьями:
Кодинг, CSS и SQL