การใช้ตัวแปรในไฟล์กำหนดค่า Apache เพื่อลดความซ้ำซ้อน?


67

เป็นไปได้หรือไม่ที่จะใช้ตัวแปรในไฟล์ Apache config

ตัวอย่างเช่นเมื่อฉันตั้งค่าไซต์ด้วย Django + WSGI ไฟล์ config อาจมีลักษณะดังนี้:

<Directory /path/to/foo/>
    Order allow,deny
    Allow from all
</Directory>
Alias /foo/static /path/to/foo/static
WSGIScriptAlias /foo /path/to/foo/run_wsgi

และฉันต้องการเปลี่ยน '/ path / to / foo' ให้เป็นตัวแปรดังนั้นจึงจำเป็นต้องกำหนดไว้ในที่เดียวเท่านั้น สิ่งที่ต้องการ:

Variable FOO /path/to/foo
…

ขอบคุณ!

คำตอบ:


66

คุณสามารถใช้mod_macroซึ่งรวมอยู่ใน Apache httpd ตั้งแต่รุ่น 2.4

ก่อนที่จะว่ามันจะต้องมีการติดตั้งแยกต่างหากดูmod_macro ยกตัวอย่างเช่นใน apt-get install libapache2-mod-macro; a2enmod macroDebian:

ตัวอย่างการกำหนดค่า

/etc/apache2/conf.d/vhost.macro

<Macro VHost $host $port>
  <VirtualHost $host:$port>

    ServerName $host
    DocumentRoot /var/vhosts/$host

    <Directory /var/vhosts/$host>
      # do something here...
    </Directory>
  </VirtualHost>
</Macro>

/etc/apache2/sites-available/vhost.mysite.com

Use VHost vhost.mysite.com 80

1
อานั่นดูเหมือนว่าฉันต้องการ อัปยศมันไม่ได้สร้างขึ้นใน ... แต่ฉันคิดว่าฉันสามารถมีชีวิตอยู่ ขอบคุณ!
David Wolever

3
ยอดเยี่ยม! นี่คือสิ่งที่ฉันวางแผนไว้ว่าจะทำได้ดีกว่าที่คิดไว้มากที่สุด
SpoonMeiser

5
@SpoonMeiser โมดูลนี้รวมเข้ากับ Apache HTTP Server จากเวอร์ชั่น 2.4.6 httpd.apache.org/docs/current/mod/mod_macro.html
ลุดวิกที่

24

ง่ายกว่าการใช้Defineคำหลัก ดูกำหนด Directive

Define RVM_ROOT /opt/rvmdir/gems
Define RUBY_18 ruby-1.8.7-head

...

SetEnv GEM_HOME ${RVM_ROOT}/${RUBY_18}@typo55
SetEnv GEM_PATH ${RVM_ROOT}/${RUBY_18}@typo55:${RVM_ROOT}/${RUBY_18}@global

2
ยอดเยี่ยม มันใช้งานได้ดีอย่างสมบูรณ์
David Tonhofer

โปรดทราบว่าThe variable is always globally defined and not limited to the scope of the surrounding config section.มันอาจหมายถึง (ฉันไม่ได้ทดสอบตอนนี้) ถ้าคุณมีหลายโฮสต์คุณไม่สามารถใช้ตัวแปรเดียวกัน (ด้วยค่าที่แตกต่างกัน) สำหรับแต่ละ
Pierre-Olivier Vares

@ Pierre-OlivierVares แก้ไขให้ดูว่าเป็นค่าคงที่ นี่คือเหตุผลที่ฉันใช้ตัวพิมพ์ใหญ่ ฉันกำหนดพวกเขาทั่วโลกนอก VirtualHost
Mathieu J.

14

คุณสามารถเปิดใช้งานหรือปิดใช้งานบิตของการกำหนดค่าด้วยIfDefineแต่นั่นอาจจะไม่ทำสิ่งที่คุณต้องการ คุณสามารถตั้งค่าตัวแปรสภาพแวดล้อมในสคริปต์เริ่มต้น Apache ให้เข้าถึงภายในการกำหนดค่าแทน ตัวอย่างเช่นการเพิ่ม:

HOSTNAME=$(hostname)

ถึง/etc/init.d/httpd(ก่อนบรรทัดที่เรียกhttpd!) บนเครื่อง RHEL ผ่านชื่อโฮสต์ของเครื่องเป็นตัวแปร ไม่จำเป็นต้องเป็นผลลัพธ์ของคำสั่ง - สิ่งใดก็ตามที่ตั้งค่าตัวแปรในสภาพแวดล้อมที่เรียกใช้งานhttpdได้ดี ตัวแปรสามารถใช้ในการกำหนดค่าดังนี้:

[root@dev ~]# cat /etc/httpd/conf.d/test.conf
Header set X-Hostname ${HOSTNAME}

[root@dev ~]# GET -Sed http://localhost
GET http://localhost --> 200 OK
Connection: close
Date: Fri, 11 Sep 2009 20:47:13 GMT
Server: Apache/2.2.3 (Red Hat)
Content-Length: 525
Content-Type: text/html;charset=ISO-8859-1
Client-Date: Fri, 11 Sep 2009 20:47:13 GMT
Client-Peer: 127.0.0.1:80
Client-Response-Num: 1
Title: Index of /
X-Hostname: dev.local

แน่นอนคุณไม่ได้ถูก จำกัด ในHeaderคำสั่ง ตัวแปรสามารถใช้ได้ทุกที่เช่น<Directory ${FOO}>อื่น ๆ

หากคุณไม่ชอบสิ่งนี้ (และมันก็ไม่ได้ดี .. ) คุณสามารถสร้างการกำหนดค่าจากแม่แบบโดยใช้m4หรือภาษาแม่แบบอื่น ๆ

เพิ่มเติม :

Hrm วิธีหนึ่งที่จะทำให้ดีขึ้นคือการเก็บตัวแปรทั้งหมดไว้ในไฟล์ภายนอกบางที/etc/httpd/conf/variables.txt:

FOO=/path/to/dir
ROLE=development

จากนั้นรวมสิ่งเหล่านี้ลงในinit.dสคริปต์Apache ของคุณด้วย:

. /etc/httpd/conf/variables

httpdก่อนที่จะเรียก ยังไม่สว่าง แต่อย่างน้อยก็แยกสคริปต์เริ่มต้นและตัวแปร


hhmm …ขอบคุณ - ในขณะที่คุณพูดสิ่งนี้ไม่ค่อยดีเท่าที่ฉันหวังไว้มันดีกว่าไม่มีอะไรเลย ขอบคุณ
David Wolever

11
ตำแหน่งที่ดีขึ้น (และสะอาดขึ้น) สำหรับตัวแปรสภาพแวดล้อมเหล่านี้คือ/etc/sysconfig/httpd(RedHat, CentOS) หรือ/etc/apache2/envvars(Ubuntu / Debian) ตัวแปรสภาพแวดล้อมบางตัวมีอยู่แล้ว
Stefan Lasiewski

7

คุณสามารถใช้ตัวแปรสภาพแวดล้อมของระบบด้วย mod_env และคำสั่ง PassEnv ดูที่นี่

ตัวอย่างสำหรับเดเบียน:

เพิ่มตัวแปรของคุณใน / etc / apache2 / envvars (ไฟล์นี้ใช้โดย apache2ctl เพื่อกำหนดตัวแปร)

...
export APACHE_PID_FILE=/var/run/apache2.pid
export HOSTNAME=$(hostname)

ส่งตัวแปรของคุณไปยังการตั้งค่า apache

PassEnv HOSTNAME

จากนั้นคุณสามารถเข้าถึงตัวแปรสภาพแวดล้อมของระบบเช่นถ้าเป็นตัวแปร apache

Header set Served-By %{HOSTNAME}e

1
ขอบคุณมาก - แม้ว่าสิ่งนี้ไม่ได้ให้คำตอบกับฉันใน apache 2.2 centos 6.4 - มันชี้ให้ฉันในทิศทางที่ถูกต้อง +1
danday74

สิ่งนี้ต้องใช้ mod_define ซึ่งไม่ได้โหลดใน apache2.2 เป็นค่าเริ่มต้น
โทมัส

3

ฉันมีปัญหาเดียวกันและหลังจากการวิจัยบางโซลูชั่นสำหรับ Apache 2.x ที่ว่าแก้ไขได้สำหรับฉัน (และไม่มีอะไรเพิ่มเติม) เป็นแบบนี้:

http://people.apache.org/~rjung/mod_define/

ระวังว่าหลังจากแกะกล่องออกแล้วคุณควรสร้างมันขึ้นมาอย่างนั้น (ส่วนการติดตั้งของเอกสารดูเหมือนจะลืมที่จะยึดติดกับ apache2?):

apxs2 -cia mod_define.c

จากนั้นสร้าง/etc/apache2/mods-available/define.load:

LoadModule define_module /usr/lib/apache2/modules/mod_define.so

หลังจากนั้นให้เปิดใช้งานโมดูลโดยใช้a2enmodตามปกติ

เอกสารในลิงก์ด้านบนแสดงวิธีใช้งาน ตอนนี้คุณสามารถกำหนดสิ่งต่างๆและใช้งานได้โดยตรงทั้งหมดนี้อยู่ในการกำหนดค่า apache2 เดียวกัน


ในกรณีที่ยังไม่ชัดเจนฟังก์ชันการทำงานแบบเดียวกันนี้จะมีให้ใช้งานตามค่าเริ่มต้นใน Apache 2.4
ColinM

2

ไม่น่าเชื่อ แต่บน httpd 2.2 บน centos 6.4 สิ่งนี้ใช้ได้

ส่งออก env vars ใน / etc / sysconfig / httpd

export mydocroot=/var/www/html

จากนั้นก็ทำสิ่งนี้ ...

<VirtualHost *:80>
  DocumentRoot ${mydocroot}
</VirtualHost>

จากนั้นในที่สุดก็ ....

service httpd restart;

อาจเป็นเพราะ/etc/sysconfig/httpdเนื้อหา(บางส่วน) เข้าสู่httpd -D(เทียบเท่ากับdefineคำสั่ง) ซึ่งกำหนดตัวแปรอาปาเช่

1

คุณอาจต้องการค้นหาmod_passengerสำหรับ apache ซึ่งสามารถโฮสต์แอพ django เราใช้มันกับความสำเร็จที่ยิ่งใหญ่ สิ่งที่คุณต้องทำใน vhost คืออืมไม่มีอะไรแน่นอน สิ่งเดียวที่คุณต้องการคือการสร้าง "สาธารณะ" dir ในรูทแอปพลิเคชันและสร้าง symlink ใน "สาธารณะ" ไปยังไดเรกทอรีคงที่ของคุณเช่น "สื่อ" (ซึ่งจะเพิ่มประสิทธิภาพการให้บริการคงที่) และชี้ DocumentRoot ของคุณ

จากนั้นวางไฟล์ต่อไปนี้ใน "public /../ ผู้โดยสาร_wsgi.py":

import sys, os
current_dir = os.path.dirname(os.path.abspath(__file__))
sys.path.append(current_dir)
sys.path.append('/PATH/TO/PACKAGES') # optional
os.environ['DJANGO_SETTINGS_MODULE'] = 'settings'
import django.core.handlers.wsgi
application = django.core.handlers.wsgi.WSGIHandler()

ไฟเบราว์เซอร์ของคุณ: ใช้งานได้!

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.